1-- |
2-- Module      : Crypto.Cipher.TripleDES
3-- License     : BSD-style
4-- Stability   : experimental
5-- Portability : ???
6
7module Crypto.Cipher.TripleDES
8    ( DES_EEE3
9    , DES_EDE3
10    , DES_EEE2
11    , DES_EDE2
12    ) where
13
14import           Data.Word
15import           Crypto.Error
16import           Crypto.Cipher.Types
17import           Crypto.Cipher.DES.Primitive
18import           Crypto.Internal.ByteArray (ByteArrayAccess)
19import qualified Crypto.Internal.ByteArray as B
20import           Data.Memory.Endian
21
22-- | 3DES with 3 different keys used all in the same direction
23data DES_EEE3 = DES_EEE3 Word64 Word64 Word64
24    deriving (Eq)
25
26-- | 3DES with 3 different keys used in alternative direction
27data DES_EDE3 = DES_EDE3 Word64 Word64 Word64
28    deriving (Eq)
29
30-- | 3DES where the first and third keys are equal, used in the same direction
31data DES_EEE2 = DES_EEE2 Word64 Word64 -- key1 and key3 are equal
32    deriving (Eq)
33
34-- | 3DES where the first and third keys are equal, used in alternative direction
35data DES_EDE2 = DES_EDE2 Word64 Word64 -- key1 and key3 are equal
36    deriving (Eq)
37
38instance Cipher DES_EEE3 where
39    cipherName    _ = "3DES_EEE"
40    cipherKeySize _ = KeySizeFixed 24
41    cipherInit k    = init3DES DES_EEE3 k
42
43instance Cipher DES_EDE3 where
44    cipherName    _ = "3DES_EDE"
45    cipherKeySize _ = KeySizeFixed 24
46    cipherInit k    = init3DES DES_EDE3 k
47
48instance Cipher DES_EDE2 where
49    cipherName    _ = "2DES_EDE"
50    cipherKeySize _ = KeySizeFixed 16
51    cipherInit k    = init2DES DES_EDE2 k
52
53instance Cipher DES_EEE2 where
54    cipherName    _ = "2DES_EEE"
55    cipherKeySize _ = KeySizeFixed 16
56    cipherInit k    = init2DES DES_EEE2 k
57
58instance BlockCipher DES_EEE3 where
59    blockSize _ = 8
60    ecbEncrypt (DES_EEE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (encrypt k3 . encrypt k2 . encrypt k1) . Block)
61    ecbDecrypt (DES_EEE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (decrypt k1 . decrypt k2 . decrypt k3) . Block)
62
63instance BlockCipher DES_EDE3 where
64    blockSize _ = 8
65    ecbEncrypt (DES_EDE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (encrypt k3 . decrypt k2 . encrypt k1) . Block)
66    ecbDecrypt (DES_EDE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (decrypt k1 . encrypt k2 . decrypt k3) . Block)
67
68instance BlockCipher DES_EEE2 where
69    blockSize _ = 8
70    ecbEncrypt (DES_EEE2 k1 k2) = B.mapAsWord64 (unBlock . (encrypt k1 . encrypt k2 . encrypt k1) . Block)
71    ecbDecrypt (DES_EEE2 k1 k2) = B.mapAsWord64 (unBlock . (decrypt k1 . decrypt k2 . decrypt k1) . Block)
72
73instance BlockCipher DES_EDE2 where
74    blockSize _ = 8
75    ecbEncrypt (DES_EDE2 k1 k2) = B.mapAsWord64 (unBlock . (encrypt k1 . decrypt k2 . encrypt k1) . Block)
76    ecbDecrypt (DES_EDE2 k1 k2) = B.mapAsWord64 (unBlock . (decrypt k1 . encrypt k2 . decrypt k1) . Block)
77
78init3DES :: ByteArrayAccess key => (Word64 -> Word64 -> Word64 -> a) -> key -> CryptoFailable a
79init3DES constr k
80    | len == 24 = CryptoPassed $ constr k1 k2 k3
81    | otherwise = CryptoFailed CryptoError_KeySizeInvalid
82  where len = B.length k
83        (k1, k2, k3) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8, fromBE $ B.toW64BE k 16)
84
85init2DES :: ByteArrayAccess key => (Word64 -> Word64 -> a) -> key -> CryptoFailable a
86init2DES constr k
87    | len == 16 = CryptoPassed $ constr k1 k2
88    | otherwise = CryptoFailed CryptoError_KeySizeInvalid
89  where len = B.length k
90        (k1, k2) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8)
91