1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
module Crypto.Cipher.Tests.KATs
where
import Data.ByteString (ByteString)
import Test.Framework (Test, testGroup, TestName)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit ((@?=))
import Crypto.Cipher.Types
import Data.Maybe
-- | ECB KAT
data KAT_ECB = KAT_ECB
{ ecbKey :: ByteString -- ^ Key
, ecbPlaintext :: ByteString -- ^ Plaintext
, ecbCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq)
-- | CBC KAT
data KAT_CBC = KAT_CBC
{ cbcKey :: ByteString -- ^ Key
, cbcIV :: ByteString -- ^ IV
, cbcPlaintext :: ByteString -- ^ Plaintext
, cbcCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq)
-- | CFB KAT
data KAT_CFB = KAT_CFB
{ cfbKey :: ByteString -- ^ Key
, cfbIV :: ByteString -- ^ IV
, cfbPlaintext :: ByteString -- ^ Plaintext
, cfbCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq)
-- | CTR KAT
data KAT_CTR = KAT_CTR
{ ctrKey :: ByteString -- ^ Key
, ctrIV :: ByteString -- ^ IV (usually represented as a 128 bits integer)
, ctrPlaintext :: ByteString -- ^ Plaintext
, ctrCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq)
-- | XTS KAT
data KAT_XTS = KAT_XTS
{ xtsKey1 :: ByteString -- ^ 1st XTS key
, xtsKey2 :: ByteString -- ^ 2nd XTS key
, xtsIV :: ByteString -- ^ XTS IV
, xtsPlaintext :: ByteString -- ^ plaintext
, xtsCiphertext :: ByteString -- ^ Ciphertext
} deriving (Show,Eq)
-- | AEAD KAT
data KAT_AEAD = KAT_AEAD
{ aeadMode :: AEADMode -- ^ AEAD mode to use
, aeadKey :: ByteString -- ^ Key
, aeadIV :: ByteString -- ^ IV for initialization
, aeadHeader :: ByteString -- ^ Authentificated Header
, aeadPlaintext :: ByteString -- ^ Plaintext
, aeadCiphertext :: ByteString -- ^ Ciphertext
, aeadTaglen :: Int -- ^ aead tag len
, aeadTag :: AuthTag -- ^ expected tag
} deriving (Show,Eq)
-- | all the KATs. use defaultKATs to prevent compilation error
-- from future expansion of this data structure
data KATs = KATs
{ kat_ECB :: [KAT_ECB]
, kat_CBC :: [KAT_CBC]
, kat_CFB :: [KAT_CFB]
, kat_CTR :: [KAT_CTR]
, kat_XTS :: [KAT_XTS]
, kat_AEAD :: [KAT_AEAD]
} deriving (Show,Eq)
-- | KAT for Stream cipher
data KAT_Stream = KAT_Stream
{ streamKey :: ByteString
, streamPlaintext :: ByteString
, streamCiphertext :: ByteString
} deriving (Show,Eq)
-- | the empty KATs
defaultKATs :: KATs
defaultKATs = KATs
{ kat_ECB = []
, kat_CBC = []
, kat_CFB = []
, kat_CTR = []
, kat_XTS = []
, kat_AEAD = []
}
-- | the empty KATs for stream
defaultStreamKATs :: [KAT_Stream]
defaultStreamKATs = []
-- | tests related to KATs
testKATs :: BlockCipher cipher
=> KATs
-> cipher
-> Test
testKATs kats cipher = testGroup "KAT"
( maybeGroup makeECBTest "ECB" (kat_ECB kats)
++ maybeGroup makeCBCTest "CBC" (kat_CBC kats)
++ maybeGroup makeCFBTest "CFB" (kat_CFB kats)
++ maybeGroup makeCTRTest "CTR" (kat_CTR kats)
++ maybeGroup makeXTSTest "XTS" (kat_XTS kats)
++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats)
)
where makeECBTest i d =
[ testCase ("E" ++ i) (ecbEncrypt ctx (ecbPlaintext d) @?= ecbCiphertext d)
, testCase ("D" ++ i) (ecbDecrypt ctx (ecbCiphertext d) @?= ecbPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ ecbKey d)
makeCBCTest i d =
[ testCase ("E" ++ i) (cbcEncrypt ctx iv (cbcPlaintext d) @?= cbcCiphertext d)
, testCase ("D" ++ i) (cbcDecrypt ctx iv (cbcCiphertext d) @?= cbcPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ cbcKey d)
iv = cipherMakeIV cipher $ cbcIV d
makeCFBTest i d =
[ testCase ("E" ++ i) (cfbEncrypt ctx iv (cfbPlaintext d) @?= cfbCiphertext d)
, testCase ("D" ++ i) (cfbDecrypt ctx iv (cfbCiphertext d) @?= cfbPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ cfbKey d)
iv = cipherMakeIV cipher $ cfbIV d
makeCTRTest i d =
[ testCase ("E" ++ i) (ctrCombine ctx iv (ctrPlaintext d) @?= ctrCiphertext d)
, testCase ("D" ++ i) (ctrCombine ctx iv (ctrCiphertext d) @?= ctrPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ ctrKey d)
iv = cipherMakeIV cipher $ ctrIV d
makeXTSTest i d =
[ testCase ("E" ++ i) (xtsEncrypt ctx iv 0 (xtsPlaintext d) @?= xtsCiphertext d)
, testCase ("D" ++ i) (xtsDecrypt ctx iv 0 (xtsCiphertext d) @?= xtsPlaintext d)
]
where ctx1 = cipherInit (cipherMakeKey cipher $ xtsKey1 d)
ctx2 = cipherInit (cipherMakeKey cipher $ xtsKey2 d)
ctx = (ctx1, ctx2)
iv = cipherMakeIV cipher $ xtsIV d
makeAEADTest i d =
[ testCase ("AE" ++ i) (etag @?= aeadTag d)
, testCase ("AD" ++ i) (dtag @?= aeadTag d)
, testCase ("E" ++ i) (ebs @?= aeadCiphertext d)
, testCase ("D" ++ i) (dbs @?= aeadPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ aeadKey d)
(Just aead) = aeadInit (aeadMode d) ctx (aeadIV d)
aeadHeaded = aeadAppendHeader aead (aeadHeader d)
(ebs,aeadEFinal) = aeadEncrypt aeadHeaded (aeadPlaintext d)
(dbs,aeadDFinal) = aeadDecrypt aeadHeaded (aeadCiphertext d)
etag = aeadFinalize aeadEFinal (aeadTaglen d)
dtag = aeadFinalize aeadDFinal (aeadTaglen d)
testStreamKATs :: StreamCipher cipher => [KAT_Stream] -> cipher -> Test
testStreamKATs kats cipher = testGroup "KAT" $ maybeGroup makeStreamTest "Stream" kats
where makeStreamTest i d =
[ testCase ("E" ++ i) (fst (streamCombine ctx (streamPlaintext d)) @?= streamCiphertext d)
, testCase ("D" ++ i) (fst (streamCombine ctx (streamCiphertext d)) @?= streamPlaintext d)
]
where ctx = cipherInit (cipherMakeKey cipher $ streamKey d)
cipherMakeKey :: Cipher cipher => cipher -> ByteString -> Key cipher
cipherMakeKey c bs = case makeKey bs of
Left e -> error ("invalid key " ++ show bs ++ " for " ++ show (cipherName c) ++ " " ++ show e)
Right k -> k
cipherMakeIV :: BlockCipher cipher => cipher -> ByteString -> IV cipher
cipherMakeIV _ bs = fromJust $ makeIV bs
maybeGroup :: (String -> t -> [Test]) -> TestName -> [t] -> [Test]
maybeGroup mkTest groupName l
| null l = []
| otherwise = [testGroup groupName (concatMap (\(i, d) -> mkTest (show i) d) $ zip nbs l)]
where nbs :: [Int]
nbs = [0..]
|