crypto-cipher-tests 0.0.10 → 0.0.11
raw patch · 5 files changed
+148/−71 lines, 5 filesdep ~crypto-cipher-types
Dependency ranges changed: crypto-cipher-types
Files
- Crypto/Cipher/Tests.hs +9/−0
- Crypto/Cipher/Tests/KATs.hs +8/−4
- Crypto/Cipher/Tests/Properties.hs +113/−60
- crypto-cipher-tests.cabal +3/−3
- tests/Tests.hs +15/−4
Crypto/Cipher/Tests.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE ViewPatterns #-} module Crypto.Cipher.Tests ( testBlockCipher+ , testBlockCipherIO , testStreamCipher -- * KATs , defaultKATs@@ -26,6 +27,7 @@ import Test.Framework (Test, testGroup) import Crypto.Cipher.Types+import Crypto.Cipher.Types.Unsafe import Crypto.Cipher.Tests.KATs import Crypto.Cipher.Tests.Properties @@ -34,6 +36,13 @@ testBlockCipher kats cipher = testGroup (cipherName cipher) ( (if kats == defaultKATs then [] else [testKATs kats cipher]) ++ testModes cipher+ )++-- | Return test for a specific blockcipher and a list of KATs+testBlockCipherIO :: BlockCipherIO a => KATs -> a -> Test+testBlockCipherIO _ cipher = testGroup ("mutable " ++ cipherName cipher)+ ( []+ ++ testIOModes cipher ) -- | Return tests for a specific streamcipher and a list of KATs
Crypto/Cipher/Tests/KATs.hs view
@@ -95,7 +95,10 @@ defaultStreamKATs = [] -- | tests related to KATs-testKATs :: BlockCipher cipher => KATs -> cipher -> Test+testKATs :: BlockCipher cipher+ => KATs+ -> cipher+ -> Test testKATs kats cipher = testGroup "KAT" ( maybeGroup makeECBTest "ECB" (kat_ECB kats) ++ maybeGroup makeCBCTest "CBC" (kat_CBC kats)@@ -149,9 +152,6 @@ etag = aeadFinalize aeadEFinal (aeadTaglen d) dtag = aeadFinalize aeadDFinal (aeadTaglen d) - cipherMakeIV :: BlockCipher cipher => cipher -> ByteString -> IV cipher- cipherMakeIV _ bs = fromJust $ makeIV bs- testStreamKATs :: StreamCipher cipher => [KAT_Stream] -> cipher -> Test testStreamKATs kats cipher = testGroup "KAT" $ maybeGroup makeStreamTest "Stream" kats where makeStreamTest i d =@@ -164,6 +164,10 @@ 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
Crypto/Cipher/Tests/Properties.hs view
@@ -10,39 +10,56 @@ import Test.QuickCheck import Crypto.Cipher.Types+import Crypto.Cipher.Types.Unsafe import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B import Data.Byteable import Data.Maybe +-- | any sized bytestring+newtype Plaintext a = Plaintext B.ByteString+ deriving (Show,Eq)++instance Byteable (Plaintext a) where+ toBytes (Plaintext b) = b++-- | A multiple of blocksize bytestring+newtype PlaintextBS a = PlaintextBS B.ByteString+ deriving (Show,Eq)++instance Byteable (PlaintextBS a) where+ toBytes (PlaintextBS b) = b+ -- | a ECB unit test-data ECBUnit a = ECBUnit (Key a) B.ByteString+data ECBUnit a = ECBUnit (Key a) (PlaintextBS a) deriving (Eq) -- | a CBC unit test-data CBCUnit a = CBCUnit (Key a) (IV a) B.ByteString+data CBCUnit a = CBCUnit (Key a) (IV a) (PlaintextBS a) deriving (Eq) -- | a CBC unit test-data CFBUnit a = CFBUnit (Key a) (IV a) B.ByteString+data CFBUnit a = CFBUnit (Key a) (IV a) (PlaintextBS a) deriving (Eq) -- | a CFB unit test-data CFB8Unit a = CFB8Unit (Key a) (IV a) B.ByteString+data CFB8Unit a = CFB8Unit (Key a) (IV a) (Plaintext a) deriving (Eq) -- | a CTR unit test-data CTRUnit a = CTRUnit (Key a) (IV a) B.ByteString+data CTRUnit a = CTRUnit (Key a) (IV a) (Plaintext a) deriving (Eq) -- | a XTS unit test-data XTSUnit a = XTSUnit (Key a) (Key a) (IV a) B.ByteString+data XTSUnit a = XTSUnit (Key a) (Key a) (IV a) (PlaintextBS a) deriving (Eq) -- | a AEAD unit test-data AEADUnit a = AEADUnit (Key a) B.ByteString B.ByteString B.ByteString+data AEADUnit a = AEADUnit (Key a) B.ByteString (Plaintext a) (Plaintext a) deriving (Eq) -data StreamUnit a = StreamUnit (Key a) B.ByteString+-- | Stream cipher unit test+data StreamUnit a = StreamUnit (Key a) (Plaintext a) deriving (Eq) instance Show (ECBUnit a) where@@ -83,27 +100,27 @@ generateIvAEAD :: Gen B.ByteString generateIvAEAD = choose (12,90) >>= \sz -> (B.pack <$> replicateM sz arbitrary) --- | Generate a plaintext multiple of 16 bytes. TODO replace by one function that use the blockSize--- cipher instance-generatePlaintextMultiple16 :: Gen B.ByteString-generatePlaintextMultiple16 = choose (1,128) >>= \size -> replicateM (size*16) arbitrary >>= return . B.pack+-- | Generate a plaintext multiple of blocksize bytes+generatePlaintextMultipleBS :: BlockCipher a => Gen (PlaintextBS a)+generatePlaintextMultipleBS = choose (1,128) >>= \size -> replicateM (size * 16) arbitrary >>= return . PlaintextBS . B.pack -generatePlaintext :: Gen B.ByteString-generatePlaintext = choose (0,324) >>= \size -> replicateM size arbitrary >>= return . B.pack+-- | Generate any sized plaintext+generatePlaintext :: Gen (Plaintext a)+generatePlaintext = choose (0,324) >>= \size -> replicateM size arbitrary >>= return . Plaintext . B.pack instance BlockCipher a => Arbitrary (ECBUnit a) where arbitrary = ECBUnit <$> generateKey- <*> generatePlaintextMultiple16+ <*> generatePlaintextMultipleBS instance BlockCipher a => Arbitrary (CBCUnit a) where arbitrary = CBCUnit <$> generateKey <*> generateIv- <*> generatePlaintextMultiple16+ <*> generatePlaintextMultipleBS instance BlockCipher a => Arbitrary (CFBUnit a) where arbitrary = CFBUnit <$> generateKey <*> generateIv- <*> generatePlaintextMultiple16+ <*> generatePlaintextMultipleBS instance BlockCipher a => Arbitrary (CFB8Unit a) where arbitrary = CFB8Unit <$> generateKey <*> generateIv <*> generatePlaintext@@ -117,7 +134,7 @@ arbitrary = XTSUnit <$> generateKey <*> generateKey <*> generateIv- <*> generatePlaintextMultiple16+ <*> generatePlaintextMultipleBS instance BlockCipher a => Arbitrary (AEADUnit a) where arbitrary = AEADUnit <$> generateKey@@ -129,62 +146,54 @@ arbitrary = StreamUnit <$> generateKey <*> generatePlaintext --- | Test a generic block cipher for properties--- related to block cipher modes.-testModes :: BlockCipher a => a -> [Test]-testModes cipher =- [ testGroup "decrypt.encrypt==id"- [ testProperty "ECB" ecbProp- , testProperty "CBC" cbcProp- , testProperty "CFB" cfbProp- , testProperty "CFB8" cfb8Prop- , testProperty "CTR" ctrProp- , testProperty "XTS" xtsProp- , testProperty "OCB" (aeadProp AEAD_OCB)- , testProperty "CCM" (aeadProp AEAD_CCM)- , testProperty "EAX" (aeadProp AEAD_EAX)- , testProperty "CWC" (aeadProp AEAD_CWC)- , testProperty "GCM" (aeadProp AEAD_GCM)- ]+testBlockCipherBasic :: BlockCipher a => a -> [Test]+testBlockCipherBasic cipher = [ testProperty "ECB" ecbProp ]+ where ecbProp = toTests cipher+ toTests :: BlockCipher a => a -> (ECBUnit a -> Bool)+ toTests _ = testProperty_ECB+ testProperty_ECB (ECBUnit (cipherInit -> ctx) (toBytes -> plaintext)) =+ plaintext `assertEq` ecbDecrypt ctx (ecbEncrypt ctx plaintext)++testBlockCipherModes :: BlockCipher a => a -> [Test]+testBlockCipherModes cipher =+ [ testProperty "CBC" cbcProp+ , testProperty "CFB" cfbProp+ , testProperty "CFB8" cfb8Prop+ , testProperty "CTR" ctrProp ]- where (ecbProp,cbcProp,cfbProp,cfb8Prop,ctrProp,xtsProp,aeadProp) = toTests cipher+ where (cbcProp,cfbProp,cfb8Prop,ctrProp) = toTests cipher toTests :: BlockCipher a => a- -> ((ECBUnit a -> Bool),- (CBCUnit a -> Bool),- (CFBUnit a -> Bool),- (CFB8Unit a -> Bool),- (CTRUnit a -> Bool),- (XTSUnit a -> Bool),- (AEADMode -> AEADUnit a -> Bool))- toTests _ = (testProperty_ECB- ,testProperty_CBC+ -> ((CBCUnit a -> Bool), (CFBUnit a -> Bool), (CFB8Unit a -> Bool), (CTRUnit a -> Bool))+ toTests _ = (testProperty_CBC ,testProperty_CFB ,testProperty_CFB8 ,testProperty_CTR- ,testProperty_XTS- ,testProperty_AEAD )- testProperty_ECB (ECBUnit (cipherInit -> ctx) plaintext) =- plaintext `assertEq` ecbDecrypt ctx (ecbEncrypt ctx plaintext)-- testProperty_CBC (CBCUnit (cipherInit -> ctx) testIV plaintext) =+ testProperty_CBC (CBCUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) = plaintext `assertEq` cbcDecrypt ctx testIV (cbcEncrypt ctx testIV plaintext) - testProperty_CFB (CFBUnit (cipherInit -> ctx) testIV plaintext) =+ testProperty_CFB (CFBUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) = plaintext `assertEq` cfbDecrypt ctx testIV (cfbEncrypt ctx testIV plaintext) - testProperty_CFB8 (CFB8Unit (cipherInit -> ctx) testIV plaintext) =+ testProperty_CFB8 (CFB8Unit (cipherInit -> ctx) testIV (toBytes -> plaintext)) = plaintext `assertEq` cfb8Decrypt ctx testIV (cfb8Encrypt ctx testIV plaintext) - testProperty_CTR (CTRUnit (cipherInit -> ctx) testIV plaintext) =+ testProperty_CTR (CTRUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) = plaintext `assertEq` ctrCombine ctx testIV (ctrCombine ctx testIV plaintext) - testProperty_XTS (XTSUnit (cipherInit -> ctx1) (cipherInit -> ctx2) testIV plaintext)- | blockSize ctx1 == 16 = plaintext `assertEq` xtsDecrypt (ctx1, ctx2) testIV 0 (xtsEncrypt (ctx1, ctx2) testIV 0 plaintext)- | otherwise = True-- testProperty_AEAD mode (AEADUnit (cipherInit -> ctx) testIV aad plaintext) =+testBlockCipherAEAD :: BlockCipher a => a -> [Test]+testBlockCipherAEAD cipher =+ [ testProperty "OCB" (aeadProp AEAD_OCB)+ , testProperty "CCM" (aeadProp AEAD_CCM)+ , testProperty "EAX" (aeadProp AEAD_EAX)+ , testProperty "CWC" (aeadProp AEAD_CWC)+ , testProperty "GCM" (aeadProp AEAD_GCM)+ ]+ where aeadProp = toTests cipher+ toTests :: BlockCipher a => a -> (AEADMode -> AEADUnit a -> Bool)+ toTests _ = testProperty_AEAD+ testProperty_AEAD mode (AEADUnit (cipherInit -> ctx) testIV (toBytes -> aad) (toBytes -> plaintext)) = case aeadInit mode ctx testIV of Just iniAead -> let aead = aeadAppendHeader iniAead aad@@ -195,10 +204,54 @@ in (plaintext `assertEq` dText) && (toBytes eTag `assertEq` toBytes dTag) Nothing -> True +testBlockCipherXTS :: BlockCipher a => a -> [Test]+testBlockCipherXTS cipher = [testProperty "XTS" xtsProp]+ where xtsProp = toTests cipher+ toTests :: BlockCipher a => a -> (XTSUnit a -> Bool)+ toTests _ = testProperty_XTS++ testProperty_XTS (XTSUnit (cipherInit -> ctx1) (cipherInit -> ctx2) testIV (toBytes -> plaintext))+ | blockSize ctx1 == 16 = plaintext `assertEq` xtsDecrypt (ctx1, ctx2) testIV 0 (xtsEncrypt (ctx1, ctx2) testIV 0 plaintext)+ | otherwise = True++-- | Test a generic block cipher for properties+-- related to block cipher modes.+testModes :: BlockCipher a => a -> [Test]+testModes cipher =+ [ testGroup "decrypt.encrypt==id"+ (testBlockCipherBasic cipher ++ testBlockCipherModes cipher ++ testBlockCipherAEAD cipher ++ testBlockCipherXTS cipher)+ ]++-- | Test a generic block cipher for properties+-- related to BlockCipherIO cipher modes.+testIOModes :: BlockCipherIO a => a -> [Test]+testIOModes cipher =+ [ testGroup "mutable"+ [ testProperty "ECB" (testProperty_ECB cipher)+ , testProperty "CBC" (testProperty_CBC cipher) ]+ ]+ where testProperty_ECB :: BlockCipherIO a => a -> (ECBUnit a) -> Bool+ testProperty_ECB _ (ECBUnit (cipherInit -> ctx) (toBytes -> plaintext)) =+ plaintext == B.unsafeCreate (B.length plaintext) encryptDecryptMutable+ where encryptDecryptMutable buf = withBytePtr plaintext $ \src -> do+ ecbEncryptMutable ctx buf src (fromIntegral $ B.length plaintext)+ ecbDecryptMutable ctx buf buf (fromIntegral $ B.length plaintext)++ testProperty_CBC :: BlockCipherIO a => a -> (CBCUnit a) -> Bool+ testProperty_CBC _ (CBCUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) =+ plaintext == B.unsafeCreate (B.length plaintext) encryptDecryptMutable+ where encryptDecryptMutable buf =+ void $ B.create (B.length plaintext) $ \tmp ->+ withBytePtr plaintext $ \src ->+ withBytePtr testIV $ \iv -> do+ cbcEncryptMutable ctx iv tmp src (fromIntegral $ B.length plaintext)+ cbcDecryptMutable ctx iv buf tmp (fromIntegral $ B.length plaintext)+ +-- | Test stream mode testStream :: StreamCipher a => a -> [Test] testStream cipher = [testProperty "combine.combine==id" (testStreamUnit cipher)] where testStreamUnit :: StreamCipher a => a -> (StreamUnit a -> Bool)- testStreamUnit _ (StreamUnit (cipherInit -> ctx) plaintext) =+ testStreamUnit _ (StreamUnit (cipherInit -> ctx) (toBytes -> plaintext)) = let cipherText = fst $ streamCombine ctx plaintext in fst (streamCombine ctx cipherText) `assertEq` plaintext
crypto-cipher-tests.cabal view
@@ -1,5 +1,5 @@ Name: crypto-cipher-tests-Version: 0.0.10+Version: 0.0.11 Synopsis: Generic cryptography cipher tests Description: Generic cryptography cipher tests License: BSD3@@ -27,7 +27,7 @@ , bytestring , byteable >= 0.1.1 && < 0.2 , securemem >= 0.1.1 && < 0.2- , crypto-cipher-types >= 0.0.7 && < 0.1+ , crypto-cipher-types >= 0.0.8 && < 0.1 ghc-options: -Wall -fwarn-tabs Test-Suite test-crypto-cipher-dummy@@ -37,7 +37,7 @@ Build-Depends: base >= 3 && < 5 , bytestring , byteable- , crypto-cipher-types >= 0.0.7+ , crypto-cipher-types , crypto-cipher-tests , mtl , QuickCheck >= 2
tests/Tests.hs view
@@ -3,6 +3,7 @@ import Test.Framework (defaultMain) import Crypto.Cipher.Types+import Crypto.Cipher.Types.Unsafe import Crypto.Cipher.Tests import qualified Data.ByteString as B import Data.Bits (xor)@@ -18,15 +19,25 @@ instance BlockCipher XorCipher where blockSize _ = 16- ecbEncrypt _ b = B.pack $ B.zipWith xor (B.replicate (B.length b) 0xa5) b- ecbDecrypt _ b = B.pack $ B.zipWith xor (B.replicate (B.length b) 0xa5) b+ ecbEncrypt _ s = xorBS s+ ecbDecrypt _ s = xorBS s +instance BlockCipherIO XorCipher where+ ecbEncryptMutable cipher d s len = onBlock cipher xorBS d s len+ ecbDecryptMutable cipher d s len = onBlock cipher xorBS d s len+ instance StreamCipher XorCipher where streamCombine _ b = (B.pack $ B.zipWith xor (B.replicate (B.length b) 0x12) b, XorCipher) +xorBS :: B.ByteString -> B.ByteString+xorBS b = B.pack $ B.zipWith xor (B.replicate (B.length b) 0xa5) b+ tests =- [ testBlockCipher defaultKATs (undefined :: XorCipher)- , testStreamCipher defaultStreamKATs (undefined :: XorCipher)+ [ testBlockCipher defaultKATs cipher+ , testBlockCipherIO defaultKATs cipher+ , testStreamCipher defaultStreamKATs cipher ]+ where cipher :: XorCipher+ cipher = undefined main = defaultMain tests