crypto-cipher-tests (empty) → 0.0.1
raw patch · 6 files changed
+372/−0 lines, 6 filesdep +HUnitdep +QuickCheckdep +basesetup-changed
Dependencies added: HUnit, QuickCheck, base, byteable, bytestring, crypto-cipher-types, mtl, securemem, test-framework, test-framework-hunit, test-framework-quickcheck2
Files
- Crypto/Cipher/Tests.hs +33/−0
- Crypto/Cipher/Tests/KATs.hs +130/−0
- Crypto/Cipher/Tests/Properties.hs +144/−0
- LICENSE +27/−0
- Setup.hs +2/−0
- crypto-cipher-tests.cabal +36/−0
+ Crypto/Cipher/Tests.hs view
@@ -0,0 +1,33 @@+-- |+-- Module : Crypto.Cipher.Tests+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : Stable+-- Portability : Excellent+--++{-# LANGUAGE ViewPatterns #-}+module Crypto.Cipher.Tests+ ( testBlockCipher+ -- * KATs+ , defaultKATs+ , KATs(..)+ , KAT_ECB(..)+ , KAT_CBC(..)+ , KAT_CTR(..)+ , KAT_XTS(..)+ , KAT_AEAD(..)+ ) where++import Test.Framework (Test, testGroup)++import Crypto.Cipher.Types+import Crypto.Cipher.Tests.KATs+import Crypto.Cipher.Tests.Properties++-- | Return tests for a specific blockcipher and a list of KATs+testBlockCipher :: BlockCipher a => KATs -> a -> Test+testBlockCipher kats cipher = testGroup (cipherName cipher)+ ( (if kats == defaultKATs then [] else [testKATs kats cipher])+ ++ testModes cipher+ )
+ Crypto/Cipher/Tests/KATs.hs view
@@ -0,0 +1,130 @@+module Crypto.Cipher.Tests.KATs+ where++import Data.ByteString (ByteString)++import Test.Framework (Test, testGroup)+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+ , ecbPlaintext :: ByteString+ , ecbCiphertext :: ByteString+ } deriving (Show,Eq)++-- | CBC KAT+data KAT_CBC = KAT_CBC+ { cbcKey :: ByteString+ , cbcIV :: ByteString+ , cbcPlaintext :: ByteString+ , cbcCiphertext :: ByteString+ } deriving (Show,Eq)++-- | CTR KAT+data KAT_CTR = KAT_CTR+ { ctrKey :: ByteString+ , ctrIV :: ByteString+ , ctrPlaintext :: ByteString+ , ctrCiphertext :: ByteString+ } deriving (Show,Eq)++-- | XTS KAT+data KAT_XTS = KAT_XTS+ { xtsKey1 :: ByteString+ , xtsKey2 :: ByteString+ , xtsIV :: ByteString+ , xtsPlaintext :: ByteString+ , xtsCiphertext :: ByteString+ } 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)++data KATs = KATs+ { kat_ECB :: [KAT_ECB]+ , kat_CBC :: [KAT_CBC]+ , kat_CTR :: [KAT_CTR]+ , kat_XTS :: [KAT_XTS]+ , kat_AEAD :: [KAT_AEAD]+ } deriving (Show,Eq)++defaultKATs :: KATs+defaultKATs = KATs+ { kat_ECB = []+ , kat_CBC = []+ , kat_CTR = []+ , kat_XTS = []+ , kat_AEAD = []+ }++testKATs :: BlockCipher cipher => KATs -> cipher -> Test+testKATs kats cipher = testGroup "KAT"+ ( maybeGroup makeECBTest "ECB" (kat_ECB kats)+ ++ maybeGroup makeCBCTest "CBC" (kat_CBC 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+ 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)+ + maybeGroup mkTest groupName l+ | null l = []+ | otherwise = [testGroup groupName (concatMap (\(i, d) -> mkTest (show i) d) $ zip nbs l)]+ nbs :: [Int]+ nbs = [0..]+ + cipherMakeKey :: BlockCipher cipher => cipher -> ByteString -> Key cipher+ cipherMakeKey _ bs = fromJust $ makeKey bs++ cipherMakeIV :: BlockCipher cipher => cipher -> ByteString -> IV cipher+ cipherMakeIV _ bs = fromJust $ makeIV bs
+ Crypto/Cipher/Tests/Properties.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE ViewPatterns #-}+module Crypto.Cipher.Tests.Properties+ where++import Control.Applicative+import Control.Monad++import Test.Framework (Test, testGroup)+import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.QuickCheck++import Crypto.Cipher.Types+import qualified Data.ByteString as B+import Data.Byteable+import Data.Maybe++-- | a ECB unit test+data ECBUnit a = ECBUnit (Key a) B.ByteString+ deriving (Eq)++-- | a CBC unit test+data CBCUnit a = CBCUnit (Key a) (IV a) B.ByteString+ deriving (Eq)++-- | a CTR unit test+data CTRUnit a = CTRUnit (Key a) (IV a) B.ByteString+ deriving (Eq)++-- | a XTS unit test+data XTSUnit a = XTSUnit (Key a) (Key a) (IV a) B.ByteString+ deriving (Eq)++-- | a AEAD unit test+data AEADUnit a = AEADUnit (Key a) B.ByteString B.ByteString B.ByteString+ deriving (Eq)++instance Show (ECBUnit a) where+ show (ECBUnit key b) = "ECB(key=" ++ show (toBytes key) ++ ",input=" ++ show b ++ ")"+instance Show (CBCUnit a) where+ show (CBCUnit key iv b) = "CBC(key=" ++ show (toBytes key) ++ ",iv=" ++ show (toBytes iv) ++ ",input=" ++ show b ++ ")"+instance Show (CTRUnit a) where+ show (CTRUnit key iv b) = "CTR(key=" ++ show (toBytes key) ++ ",iv=" ++ show (toBytes iv) ++ ",input=" ++ show b ++ ")"+instance Show (XTSUnit a) where+ show (XTSUnit key1 key2 iv b) = "XTS(key1=" ++ show (toBytes key1) ++ ",key2=" ++ show (toBytes key2) ++ ",iv=" ++ show (toBytes iv) ++ ",input=" ++ show b ++ ")"+instance Show (AEADUnit a) where+ show (AEADUnit key iv aad b) = "AEAD(key=" ++ show (toBytes key) ++ ",iv=" ++ show iv ++ ",aad=" ++ show (toBytes aad) ++ ",input=" ++ show b ++ ")"++generateKey :: BlockCipher a => Gen (Key a)+generateKey = keyFromCipher undefined+ where keyFromCipher :: BlockCipher a => a -> Gen (Key a)+ keyFromCipher cipher = case cipherKeySize cipher of+ Just sz -> fromJust . makeKey . B.pack <$> replicateM sz arbitrary+ Nothing -> fromJust . makeKey . B.pack <$> (choose (1,66) >>= \sz -> replicateM sz arbitrary)++generateIv :: BlockCipher a => Gen (IV a)+generateIv = ivFromCipher undefined+ where ivFromCipher :: BlockCipher a => a -> Gen (IV a)+ ivFromCipher cipher = fromJust . makeIV . B.pack <$> replicateM (blockSize cipher) arbitrary++generateIvAEAD :: Gen B.ByteString+generateIvAEAD = choose (12,90) >>= \sz -> (B.pack <$> replicateM sz arbitrary)++generatePlaintextMultiple16 :: Gen B.ByteString+generatePlaintextMultiple16 = choose (1,128) >>= \size -> replicateM (size*16) arbitrary >>= return . B.pack++generatePlaintext :: Gen B.ByteString+generatePlaintext = choose (0,324) >>= \size -> replicateM size arbitrary >>= return . B.pack++instance BlockCipher a => Arbitrary (ECBUnit a) where+ arbitrary = ECBUnit <$> generateKey+ <*> generatePlaintextMultiple16++instance BlockCipher a => Arbitrary (CBCUnit a) where+ arbitrary = CBCUnit <$> generateKey+ <*> generateIv+ <*> generatePlaintextMultiple16++instance BlockCipher a => Arbitrary (CTRUnit a) where+ arbitrary = CTRUnit <$> generateKey+ <*> generateIv+ <*> generatePlaintext++instance BlockCipher a => Arbitrary (XTSUnit a) where+ arbitrary = XTSUnit <$> generateKey+ <*> generateKey+ <*> generateIv+ <*> generatePlaintextMultiple16++instance BlockCipher a => Arbitrary (AEADUnit a) where+ arbitrary = AEADUnit <$> generateKey+ <*> generateIvAEAD+ <*> generatePlaintext+ <*> generatePlaintext++testModes :: BlockCipher a => a -> [Test]+testModes cipher =+ [ testGroup "decrypt.encrypt==id"+ [ testProperty "ECB" ecbProp+ , testProperty "CBC" cbcProp+ , 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)+ ]+ ]+ where (ecbProp,cbcProp,ctrProp,xtsProp,aeadProp) = toTests cipher+ toTests :: BlockCipher a+ => a+ -> ((ECBUnit a -> Bool), (CBCUnit a -> Bool), (CTRUnit a -> Bool), (XTSUnit a -> Bool), (AEADMode -> AEADUnit a -> Bool))+ toTests _ = (testProperty_ECB+ ,testProperty_CBC+ ,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) =+ plaintext `assertEq` cbcDecrypt ctx testIV (cbcEncrypt ctx testIV plaintext)++ testProperty_CTR (CTRUnit (cipherInit -> ctx) testIV plaintext) =+ plaintext `assertEq` ctrCombine ctx testIV (ctrCombine ctx testIV plaintext)++ testProperty_XTS (XTSUnit (cipherInit -> ctx1) (cipherInit -> ctx2) testIV plaintext) =+ plaintext `assertEq` xtsDecrypt (ctx1, ctx2) testIV 0 (xtsEncrypt (ctx1, ctx2) testIV 0 plaintext)++ testProperty_AEAD mode (AEADUnit (cipherInit -> ctx) testIV aad plaintext) =+ case aeadInit mode ctx testIV of+ Just iniAead ->+ let aead = aeadAppendHeader iniAead aad+ (eText, aeadE) = aeadEncrypt aead plaintext+ (dText, aeadD) = aeadDecrypt aead eText+ eTag = aeadFinalize aeadE (blockSize ctx)+ dTag = aeadFinalize aeadD (blockSize ctx)+ in (plaintext `assertEq` dText) && (toBytes eTag `assertEq` toBytes dTag)+ Nothing -> True++assertEq :: B.ByteString -> B.ByteString -> Bool+assertEq b1 b2 | b1 /= b2 = error ("b1: " ++ show b1 ++ " b2: " ++ show b2)+ | otherwise = True
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2013 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ crypto-cipher-tests.cabal view
@@ -0,0 +1,36 @@+Name: crypto-cipher-tests+Version: 0.0.1+Synopsis: Generic cryptography cipher tests+Description: Generic cryptography cipher tests+License: BSD3+License-file: LICENSE+Copyright: Vincent Hanquez <vincent@snarc.org>+Author: Vincent Hanquez <vincent@snarc.org>+Maintainer: vincent@snarc.org+Category: Cryptography+Stability: experimental+Build-Type: Simple+Homepage: http://github.com/vincenthz/hs-crypto-cipher+Cabal-Version: >=1.8++Library+ Exposed-modules: Crypto.Cipher.Tests+ Other-modules: Crypto.Cipher.Tests.KATs+ Crypto.Cipher.Tests.Properties+ Build-depends: base >= 3 && < 5+ , QuickCheck >= 2+ , mtl+ , HUnit+ , test-framework+ , test-framework-quickcheck2+ , test-framework-hunit+ , bytestring+ , byteable >= 0.1.1+ , securemem >= 0.1.1+ , crypto-cipher-types+ ghc-options: -Wall -fwarn-tabs++source-repository head+ type: git+ location: git://github.com/vincenthz/hs-crypto-cipher+ subdir: tests