    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
        { KAT_ECB -> ByteString
    ecbKey        :: ByteString -- ^ Key
        , KAT_ECB -> ByteString
    ecbPlaintext  :: ByteString -- ^ Plaintext
        , KAT_ECB -> ByteString
    ecbCiphertext :: ByteString -- ^ Ciphertext
        } deriving (Int -> KAT_ECB -> ShowS
    [KAT_ECB] -> ShowS
    KAT_ECB -> String
    (Int -> KAT_ECB -> ShowS)
    -> (KAT_ECB -> String) -> ([KAT_ECB] -> ShowS) -> Show KAT_ECB
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_ECB -> ShowS
    showsPrec :: Int -> KAT_ECB -> ShowS
    $cshow :: KAT_ECB -> String
    show :: KAT_ECB -> String
    $cshowList :: [KAT_ECB] -> ShowS
    showList :: [KAT_ECB] -> ShowS
    Show,KAT_ECB -> KAT_ECB -> Bool
    (KAT_ECB -> KAT_ECB -> Bool)
    -> (KAT_ECB -> KAT_ECB -> Bool) -> Eq KAT_ECB
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_ECB -> KAT_ECB -> Bool
    == :: KAT_ECB -> KAT_ECB -> Bool
    $c/= :: KAT_ECB -> KAT_ECB -> Bool
    /= :: KAT_ECB -> KAT_ECB -> Bool
    Eq)

    -- | CBC KAT
    data KAT_CBC = KAT_CBC
        { KAT_CBC -> ByteString
    cbcKey        :: ByteString -- ^ Key
        , KAT_CBC -> ByteString
    cbcIV         :: ByteString -- ^ IV
        , KAT_CBC -> ByteString
    cbcPlaintext  :: ByteString -- ^ Plaintext
        , KAT_CBC -> ByteString
    cbcCiphertext :: ByteString -- ^ Ciphertext
        } deriving (Int -> KAT_CBC -> ShowS
    [KAT_CBC] -> ShowS
    KAT_CBC -> String
    (Int -> KAT_CBC -> ShowS)
    -> (KAT_CBC -> String) -> ([KAT_CBC] -> ShowS) -> Show KAT_CBC
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_CBC -> ShowS
    showsPrec :: Int -> KAT_CBC -> ShowS
    $cshow :: KAT_CBC -> String
    show :: KAT_CBC -> String
    $cshowList :: [KAT_CBC] -> ShowS
    showList :: [KAT_CBC] -> ShowS
    Show,KAT_CBC -> KAT_CBC -> Bool
    (KAT_CBC -> KAT_CBC -> Bool)
    -> (KAT_CBC -> KAT_CBC -> Bool) -> Eq KAT_CBC
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_CBC -> KAT_CBC -> Bool
    == :: KAT_CBC -> KAT_CBC -> Bool
    $c/= :: KAT_CBC -> KAT_CBC -> Bool
    /= :: KAT_CBC -> KAT_CBC -> Bool
    Eq)

    -- | CFB KAT
    data KAT_CFB = KAT_CFB
        { KAT_CFB -> ByteString
    cfbKey        :: ByteString -- ^ Key
        , KAT_CFB -> ByteString
    cfbIV         :: ByteString -- ^ IV
        , KAT_CFB -> ByteString
    cfbPlaintext  :: ByteString -- ^ Plaintext
        , KAT_CFB -> ByteString
    cfbCiphertext :: ByteString -- ^ Ciphertext
        } deriving (Int -> KAT_CFB -> ShowS
    [KAT_CFB] -> ShowS
    KAT_CFB -> String
    (Int -> KAT_CFB -> ShowS)
    -> (KAT_CFB -> String) -> ([KAT_CFB] -> ShowS) -> Show KAT_CFB
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_CFB -> ShowS
    showsPrec :: Int -> KAT_CFB -> ShowS
    $cshow :: KAT_CFB -> String
    show :: KAT_CFB -> String
    $cshowList :: [KAT_CFB] -> ShowS
    showList :: [KAT_CFB] -> ShowS
    Show,KAT_CFB -> KAT_CFB -> Bool
    (KAT_CFB -> KAT_CFB -> Bool)
    -> (KAT_CFB -> KAT_CFB -> Bool) -> Eq KAT_CFB
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_CFB -> KAT_CFB -> Bool
    == :: KAT_CFB -> KAT_CFB -> Bool
    $c/= :: KAT_CFB -> KAT_CFB -> Bool
    /= :: KAT_CFB -> KAT_CFB -> Bool
    Eq)

    -- | CTR KAT
    data KAT_CTR = KAT_CTR
        { KAT_CTR -> ByteString
    ctrKey        :: ByteString -- ^ Key
        , KAT_CTR -> ByteString
    ctrIV         :: ByteString -- ^ IV (usually represented as a 128 bits integer)
        , KAT_CTR -> ByteString
    ctrPlaintext  :: ByteString -- ^ Plaintext
        , KAT_CTR -> ByteString
    ctrCiphertext :: ByteString -- ^ Ciphertext
        } deriving (Int -> KAT_CTR -> ShowS
    [KAT_CTR] -> ShowS
    KAT_CTR -> String
    (Int -> KAT_CTR -> ShowS)
    -> (KAT_CTR -> String) -> ([KAT_CTR] -> ShowS) -> Show KAT_CTR
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_CTR -> ShowS
    showsPrec :: Int -> KAT_CTR -> ShowS
    $cshow :: KAT_CTR -> String
    show :: KAT_CTR -> String
    $cshowList :: [KAT_CTR] -> ShowS
    showList :: [KAT_CTR] -> ShowS
    Show,KAT_CTR -> KAT_CTR -> Bool
    (KAT_CTR -> KAT_CTR -> Bool)
    -> (KAT_CTR -> KAT_CTR -> Bool) -> Eq KAT_CTR
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_CTR -> KAT_CTR -> Bool
    == :: KAT_CTR -> KAT_CTR -> Bool
    $c/= :: KAT_CTR -> KAT_CTR -> Bool
    /= :: KAT_CTR -> KAT_CTR -> Bool
    Eq)

    -- | XTS KAT
    data KAT_XTS = KAT_XTS
        { KAT_XTS -> ByteString
    xtsKey1       :: ByteString -- ^ 1st XTS key
        , KAT_XTS -> ByteString
    xtsKey2       :: ByteString -- ^ 2nd XTS key
        , KAT_XTS -> ByteString
    xtsIV         :: ByteString -- ^ XTS IV
        , KAT_XTS -> ByteString
    xtsPlaintext  :: ByteString -- ^ plaintext
        , KAT_XTS -> ByteString
    xtsCiphertext :: ByteString -- ^ Ciphertext
        } deriving (Int -> KAT_XTS -> ShowS
    [KAT_XTS] -> ShowS
    KAT_XTS -> String
    (Int -> KAT_XTS -> ShowS)
    -> (KAT_XTS -> String) -> ([KAT_XTS] -> ShowS) -> Show KAT_XTS
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_XTS -> ShowS
    showsPrec :: Int -> KAT_XTS -> ShowS
    $cshow :: KAT_XTS -> String
    show :: KAT_XTS -> String
    $cshowList :: [KAT_XTS] -> ShowS
    showList :: [KAT_XTS] -> ShowS
    Show,KAT_XTS -> KAT_XTS -> Bool
    (KAT_XTS -> KAT_XTS -> Bool)
    -> (KAT_XTS -> KAT_XTS -> Bool) -> Eq KAT_XTS
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_XTS -> KAT_XTS -> Bool
    == :: KAT_XTS -> KAT_XTS -> Bool
    $c/= :: KAT_XTS -> KAT_XTS -> Bool
    /= :: KAT_XTS -> KAT_XTS -> Bool
    Eq)

    -- | AEAD KAT
    data KAT_AEAD = KAT_AEAD
        { KAT_AEAD -> AEADMode
    aeadMode       :: AEADMode   -- ^ AEAD mode to use
        , KAT_AEAD -> ByteString
    aeadKey        :: ByteString -- ^ Key
        , KAT_AEAD -> ByteString
    aeadIV         :: ByteString -- ^ IV for initialization
        , KAT_AEAD -> ByteString
    aeadHeader     :: ByteString -- ^ Authentificated Header
        , KAT_AEAD -> ByteString
    aeadPlaintext  :: ByteString -- ^ Plaintext
        , KAT_AEAD -> ByteString
    aeadCiphertext :: ByteString -- ^ Ciphertext
        , KAT_AEAD -> Int
    aeadTaglen     :: Int        -- ^ aead tag len
        , KAT_AEAD -> AuthTag
    aeadTag        :: AuthTag    -- ^ expected tag
        } deriving (Int -> KAT_AEAD -> ShowS
    [KAT_AEAD] -> ShowS
    KAT_AEAD -> String
    (Int -> KAT_AEAD -> ShowS)
    -> (KAT_AEAD -> String) -> ([KAT_AEAD] -> ShowS) -> Show KAT_AEAD
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_AEAD -> ShowS
    showsPrec :: Int -> KAT_AEAD -> ShowS
    $cshow :: KAT_AEAD -> String
    show :: KAT_AEAD -> String
    $cshowList :: [KAT_AEAD] -> ShowS
    showList :: [KAT_AEAD] -> ShowS
    Show,KAT_AEAD -> KAT_AEAD -> Bool
    (KAT_AEAD -> KAT_AEAD -> Bool)
    -> (KAT_AEAD -> KAT_AEAD -> Bool) -> Eq KAT_AEAD
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_AEAD -> KAT_AEAD -> Bool
    == :: KAT_AEAD -> KAT_AEAD -> Bool
    $c/= :: KAT_AEAD -> KAT_AEAD -> Bool
    /= :: KAT_AEAD -> KAT_AEAD -> Bool
    Eq)

    -- | all the KATs. use defaultKATs to prevent compilation error
    -- from future expansion of this data structure
    data KATs = KATs
        { KATs -> [KAT_ECB]
    kat_ECB  :: [KAT_ECB]
        , KATs -> [KAT_CBC]
    kat_CBC  :: [KAT_CBC]
        , KATs -> [KAT_CFB]
    kat_CFB  :: [KAT_CFB]
        , KATs -> [KAT_CTR]
    kat_CTR  :: [KAT_CTR]
        , KATs -> [KAT_XTS]
    kat_XTS  :: [KAT_XTS]
        , KATs -> [KAT_AEAD]
    kat_AEAD :: [KAT_AEAD]
        } deriving (Int -> KATs -> ShowS
    [KATs] -> ShowS
    KATs -> String
    (Int -> KATs -> ShowS)
    -> (KATs -> String) -> ([KATs] -> ShowS) -> Show KATs
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KATs -> ShowS
    showsPrec :: Int -> KATs -> ShowS
    $cshow :: KATs -> String
    show :: KATs -> String
    $cshowList :: [KATs] -> ShowS
    showList :: [KATs] -> ShowS
    Show,KATs -> KATs -> Bool
    (KATs -> KATs -> Bool) -> (KATs -> KATs -> Bool) -> Eq KATs
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KATs -> KATs -> Bool
    == :: KATs -> KATs -> Bool
    $c/= :: KATs -> KATs -> Bool
    /= :: KATs -> KATs -> Bool
    Eq)

    -- | KAT for Stream cipher
    data KAT_Stream = KAT_Stream
        { KAT_Stream -> ByteString
    streamKey        :: ByteString
        , KAT_Stream -> ByteString
    streamPlaintext  :: ByteString
        , KAT_Stream -> ByteString
    streamCiphertext :: ByteString
        } deriving (Int -> KAT_Stream -> ShowS
    [KAT_Stream] -> ShowS
    KAT_Stream -> String
    (Int -> KAT_Stream -> ShowS)
    -> (KAT_Stream -> String)
    -> ([KAT_Stream] -> ShowS)
    -> Show KAT_Stream
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> KAT_Stream -> ShowS
    showsPrec :: Int -> KAT_Stream -> ShowS
    $cshow :: KAT_Stream -> String
    show :: KAT_Stream -> String
    $cshowList :: [KAT_Stream] -> ShowS
    showList :: [KAT_Stream] -> ShowS
    Show,KAT_Stream -> KAT_Stream -> Bool
    (KAT_Stream -> KAT_Stream -> Bool)
    -> (KAT_Stream -> KAT_Stream -> Bool) -> Eq KAT_Stream
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: KAT_Stream -> KAT_Stream -> Bool
    == :: KAT_Stream -> KAT_Stream -> Bool
    $c/= :: KAT_Stream -> KAT_Stream -> Bool
    /= :: KAT_Stream -> KAT_Stream -> Bool
    Eq)

    -- | the empty KATs
    defaultKATs :: KATs
    defaultKATs :: KATs
    defaultKATs = KATs
        { kat_ECB :: [KAT_ECB]
    kat_ECB  = []
        , kat_CBC :: [KAT_CBC]
    kat_CBC  = []
        , kat_CFB :: [KAT_CFB]
    kat_CFB  = []
        , kat_CTR :: [KAT_CTR]
    kat_CTR  = []
        , kat_XTS :: [KAT_XTS]
    kat_XTS  = []
        , kat_AEAD :: [KAT_AEAD]
    kat_AEAD = []
        }

    -- | the empty KATs for stream
    defaultStreamKATs :: [KAT_Stream]
    defaultStreamKATs :: [KAT_Stream]
    defaultStreamKATs = []

    -- | tests related to KATs
    testKATs :: BlockCipher cipher
             => KATs
             -> cipher
             -> Test
    testKATs :: forall cipher. BlockCipher cipher => KATs -> cipher -> Test
    testKATs KATs
    kats cipher
    cipher = String -> [Test] -> Test
    testGroup String
    "KAT"
        (   (String -> KAT_ECB -> [Test]) -> String -> [KAT_ECB] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_ECB -> [Test]
    makeECBTest String
    "ECB" (KATs -> [KAT_ECB]
    kat_ECB KATs
    kats)
         [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ (String -> KAT_CBC -> [Test]) -> String -> [KAT_CBC] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_CBC -> [Test]
    makeCBCTest String
    "CBC" (KATs -> [KAT_CBC]
    kat_CBC KATs
    kats)
         [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ (String -> KAT_CFB -> [Test]) -> String -> [KAT_CFB] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_CFB -> [Test]
    makeCFBTest String
    "CFB" (KATs -> [KAT_CFB]
    kat_CFB KATs
    kats)
         [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ (String -> KAT_CTR -> [Test]) -> String -> [KAT_CTR] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_CTR -> [Test]
    makeCTRTest String
    "CTR" (KATs -> [KAT_CTR]
    kat_CTR KATs
    kats)
         [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ (String -> KAT_XTS -> [Test]) -> String -> [KAT_XTS] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_XTS -> [Test]
    makeXTSTest String
    "XTS" (KATs -> [KAT_XTS]
    kat_XTS KATs
    kats)
         [Test] -> [Test] -> [Test]
    forall a. [a] -> [a] -> [a]
    ++ (String -> KAT_AEAD -> [Test]) -> String -> [KAT_AEAD] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_AEAD -> [Test]
    makeAEADTest String
    "AEAD" (KATs -> [KAT_AEAD]
    kat_AEAD KATs
    kats)
        )
      where makeECBTest :: String -> KAT_ECB -> [Test]
    makeECBTest String
    i KAT_ECB
    d =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> ByteString
    ecbEncrypt cipher
    ctx (KAT_ECB -> ByteString
    ecbPlaintext KAT_ECB
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_ECB -> ByteString
    ecbCiphertext KAT_ECB
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> ByteString
    ecbDecrypt cipher
    ctx (KAT_ECB -> ByteString
    ecbCiphertext KAT_ECB
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_ECB -> ByteString
    ecbPlaintext KAT_ECB
    d)
                ]
              where ctx :: cipher
    ctx = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_ECB -> ByteString
    ecbKey KAT_ECB
    d)
            makeCBCTest :: String -> KAT_CBC -> [Test]
    makeCBCTest String
    i KAT_CBC
    d =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    cbcEncrypt cipher
    ctx IV cipher
    iv (KAT_CBC -> ByteString
    cbcPlaintext KAT_CBC
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CBC -> ByteString
    cbcCiphertext KAT_CBC
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    cbcDecrypt cipher
    ctx IV cipher
    iv (KAT_CBC -> ByteString
    cbcCiphertext KAT_CBC
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CBC -> ByteString
    cbcPlaintext KAT_CBC
    d)
                ]
              where ctx :: cipher
    ctx = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CBC -> ByteString
    cbcKey KAT_CBC
    d)
                    iv :: IV cipher
    iv  = cipher -> ByteString -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> IV cipher
    cipherMakeIV cipher
    cipher (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CBC -> ByteString
    cbcIV KAT_CBC
    d
            makeCFBTest :: String -> KAT_CFB -> [Test]
    makeCFBTest String
    i KAT_CFB
    d =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    cfbEncrypt cipher
    ctx IV cipher
    iv (KAT_CFB -> ByteString
    cfbPlaintext KAT_CFB
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CFB -> ByteString
    cfbCiphertext KAT_CFB
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    cfbDecrypt cipher
    ctx IV cipher
    iv (KAT_CFB -> ByteString
    cfbCiphertext KAT_CFB
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CFB -> ByteString
    cfbPlaintext KAT_CFB
    d)
                ]
              where ctx :: cipher
    ctx = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CFB -> ByteString
    cfbKey KAT_CFB
    d)
                    iv :: IV cipher
    iv  = cipher -> ByteString -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> IV cipher
    cipherMakeIV cipher
    cipher (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CFB -> ByteString
    cfbIV KAT_CFB
    d
            makeCTRTest :: String -> KAT_CTR -> [Test]
    makeCTRTest String
    i KAT_CTR
    d =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    ctrCombine cipher
    ctx IV cipher
    iv (KAT_CTR -> ByteString
    ctrPlaintext KAT_CTR
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CTR -> ByteString
    ctrCiphertext KAT_CTR
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (cipher -> IV cipher -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    cipher -> IV cipher -> ByteString -> ByteString
    ctrCombine cipher
    ctx IV cipher
    iv (KAT_CTR -> ByteString
    ctrCiphertext KAT_CTR
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_CTR -> ByteString
    ctrPlaintext KAT_CTR
    d)
                ]
              where ctx :: cipher
    ctx = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CTR -> ByteString
    ctrKey KAT_CTR
    d)
                    iv :: IV cipher
    iv  = cipher -> ByteString -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> IV cipher
    cipherMakeIV cipher
    cipher (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_CTR -> ByteString
    ctrIV KAT_CTR
    d
            makeXTSTest :: String -> KAT_XTS -> [Test]
    makeXTSTest String
    i KAT_XTS
    d  =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) ((cipher, cipher)
    -> IV cipher -> DataUnitOffset -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    (cipher, cipher)
    -> IV cipher -> DataUnitOffset -> ByteString -> ByteString
    xtsEncrypt (cipher, cipher)
    ctx IV cipher
    iv DataUnitOffset
    0 (KAT_XTS -> ByteString
    xtsPlaintext KAT_XTS
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_XTS -> ByteString
    xtsCiphertext KAT_XTS
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) ((cipher, cipher)
    -> IV cipher -> DataUnitOffset -> ByteString -> ByteString
    forall cipher.
    BlockCipher cipher =>
    (cipher, cipher)
    -> IV cipher -> DataUnitOffset -> ByteString -> ByteString
    xtsDecrypt (cipher, cipher)
    ctx IV cipher
    iv DataUnitOffset
    0 (KAT_XTS -> ByteString
    xtsCiphertext KAT_XTS
    d) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_XTS -> ByteString
    xtsPlaintext KAT_XTS
    d)
                ]
              where ctx1 :: cipher
    ctx1 = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_XTS -> ByteString
    xtsKey1 KAT_XTS
    d)
                    ctx2 :: cipher
    ctx2 = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_XTS -> ByteString
    xtsKey2 KAT_XTS
    d)
                    ctx :: (cipher, cipher)
    ctx  = (cipher
    ctx1, cipher
    ctx2)
                    iv :: IV cipher
    iv   = cipher -> ByteString -> IV cipher
    forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> IV cipher
    cipherMakeIV cipher
    cipher (ByteString -> IV cipher) -> ByteString -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_XTS -> ByteString
    xtsIV KAT_XTS
    d
            makeAEADTest :: String -> KAT_AEAD -> [Test]
    makeAEADTest String
    i KAT_AEAD
    d =
                [ String -> Assertion -> Test
    testCase (String
    "AE" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (AuthTag
    etag AuthTag -> AuthTag -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_AEAD -> AuthTag
    aeadTag KAT_AEAD
    d)
                , String -> Assertion -> Test
    testCase (String
    "AD" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) (AuthTag
    dtag AuthTag -> AuthTag -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_AEAD -> AuthTag
    aeadTag KAT_AEAD
    d)
                , String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i)  (ByteString
    ebs ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_AEAD -> ByteString
    aeadCiphertext KAT_AEAD
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i)  (ByteString
    dbs ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_AEAD -> ByteString
    aeadPlaintext KAT_AEAD
    d)
                ]
              where ctx :: cipher
    ctx  = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_AEAD -> ByteString
    aeadKey KAT_AEAD
    d)
                    (Just AEAD cipher
    aead) = AEADMode -> cipher -> ByteString -> Maybe (AEAD cipher)
    forall iv.
    Byteable iv =>
    AEADMode -> cipher -> iv -> Maybe (AEAD cipher)
    forall cipher iv.
    (BlockCipher cipher, Byteable iv) =>
    AEADMode -> cipher -> iv -> Maybe (AEAD cipher)
    aeadInit (KAT_AEAD -> AEADMode
    aeadMode KAT_AEAD
    d) cipher
    ctx (KAT_AEAD -> ByteString
    aeadIV KAT_AEAD
    d)
                    aeadHeaded :: AEAD cipher
    aeadHeaded     = AEAD cipher -> ByteString -> AEAD cipher
    forall a. BlockCipher a => AEAD a -> ByteString -> AEAD a
    aeadAppendHeader AEAD cipher
    aead (KAT_AEAD -> ByteString
    aeadHeader KAT_AEAD
    d)
                    (ByteString
    ebs,AEAD cipher
    aeadEFinal) = AEAD cipher -> ByteString -> (ByteString, AEAD cipher)
    forall a.
    BlockCipher a =>
    AEAD a -> ByteString -> (ByteString, AEAD a)
    aeadEncrypt AEAD cipher
    aeadHeaded (KAT_AEAD -> ByteString
    aeadPlaintext KAT_AEAD
    d)
                    (ByteString
    dbs,AEAD cipher
    aeadDFinal) = AEAD cipher -> ByteString -> (ByteString, AEAD cipher)
    forall a.
    BlockCipher a =>
    AEAD a -> ByteString -> (ByteString, AEAD a)
    aeadDecrypt AEAD cipher
    aeadHeaded (KAT_AEAD -> ByteString
    aeadCiphertext KAT_AEAD
    d)
                    etag :: AuthTag
    etag = AEAD cipher -> Int -> AuthTag
    forall a. BlockCipher a => AEAD a -> Int -> AuthTag
    aeadFinalize AEAD cipher
    aeadEFinal (KAT_AEAD -> Int
    aeadTaglen KAT_AEAD
    d)
                    dtag :: AuthTag
    dtag = AEAD cipher -> Int -> AuthTag
    forall a. BlockCipher a => AEAD a -> Int -> AuthTag
    aeadFinalize AEAD cipher
    aeadDFinal (KAT_AEAD -> Int
    aeadTaglen KAT_AEAD
    d)

    testStreamKATs :: StreamCipher cipher => [KAT_Stream] -> cipher -> Test
    testStreamKATs :: forall cipher.
    StreamCipher cipher =>
    [KAT_Stream] -> cipher -> Test
    testStreamKATs [KAT_Stream]
    kats cipher
    cipher = String -> [Test] -> Test
    testGroup String
    "KAT" ([Test] -> Test) -> [Test] -> Test
    forall a b. (a -> b) -> a -> b
    $ (String -> KAT_Stream -> [Test])
    -> String -> [KAT_Stream] -> [Test]
    forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> KAT_Stream -> [Test]
    makeStreamTest String
    "Stream" [KAT_Stream]
    kats
      where makeStreamTest :: String -> KAT_Stream -> [Test]
    makeStreamTest String
    i KAT_Stream
    d =
                [ String -> Assertion -> Test
    testCase (String
    "E" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) ((ByteString, cipher) -> ByteString
    forall a b. (a, b) -> a
    fst (cipher -> ByteString -> (ByteString, cipher)
    forall cipher.
    StreamCipher cipher =>
    cipher -> ByteString -> (ByteString, cipher)
    streamCombine cipher
    ctx (KAT_Stream -> ByteString
    streamPlaintext KAT_Stream
    d)) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_Stream -> ByteString
    streamCiphertext KAT_Stream
    d)
                , String -> Assertion -> Test
    testCase (String
    "D" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    i) ((ByteString, cipher) -> ByteString
    forall a b. (a, b) -> a
    fst (cipher -> ByteString -> (ByteString, cipher)
    forall cipher.
    StreamCipher cipher =>
    cipher -> ByteString -> (ByteString, cipher)
    streamCombine cipher
    ctx (KAT_Stream -> ByteString
    streamCiphertext KAT_Stream
    d)) ByteString -> ByteString -> Assertion
    forall a. (HasCallStack, Eq a, Show a) => a -> a -> Assertion
    @?= KAT_Stream -> ByteString
    streamPlaintext KAT_Stream
    d)
                ]
              where ctx :: cipher
    ctx = Key cipher -> cipher
    forall cipher. Cipher cipher => Key cipher -> cipher
    cipherInit (cipher -> ByteString -> Key cipher
    forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    cipher (ByteString -> Key cipher) -> ByteString -> Key cipher
    forall a b. (a -> b) -> a -> b
    $ KAT_Stream -> ByteString
    streamKey KAT_Stream
    d)

    cipherMakeKey :: Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey :: forall cipher. Cipher cipher => cipher -> ByteString -> Key cipher
    cipherMakeKey cipher
    c ByteString
    bs = case ByteString -> Either KeyError (Key cipher)
    forall b c.
    (ToSecureMem b, Cipher c) =>
    b -> Either KeyError (Key c)
    makeKey ByteString
    bs of
                            Left KeyError
    e -> String -> Key cipher
    forall a. HasCallStack => String -> a
    error (String
    "invalid key " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    bs String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " for " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    forall a. Show a => a -> String
    show (cipher -> String
    forall cipher. Cipher cipher => cipher -> String
    cipherName cipher
    c) String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ KeyError -> String
    forall a. Show a => a -> String
    show KeyError
    e)
                            Right Key cipher
    k  -> Key cipher
    k

    cipherMakeIV :: BlockCipher cipher => cipher -> ByteString -> IV cipher
    cipherMakeIV :: forall cipher.
    BlockCipher cipher =>
    cipher -> ByteString -> IV cipher
    cipherMakeIV cipher
    _ ByteString
    bs = Maybe (IV cipher) -> IV cipher
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (IV cipher) -> IV cipher) -> Maybe (IV cipher) -> IV cipher
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Maybe (IV cipher)
    forall b c. (Byteable b, BlockCipher c) => b -> Maybe (IV c)
    makeIV ByteString
    bs

    maybeGroup :: (String -> t -> [Test]) -> TestName -> [t] -> [Test]
    maybeGroup :: forall t. (String -> t -> [Test]) -> String -> [t] -> [Test]
    maybeGroup String -> t -> [Test]
    mkTest String
    groupName [t]
    l
        | [t] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [t]
    l    = []
        | Bool
    otherwise = [String -> [Test] -> Test
    testGroup String
    groupName (((Int, t) -> [Test]) -> [(Int, t)] -> [Test]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\(Int
    i, t
    d) -> String -> t -> [Test]
    mkTest (Int -> String
    forall a. Show a => a -> String
    show Int
    i) t
    d) ([(Int, t)] -> [Test]) -> [(Int, t)] -> [Test]
    forall a b. (a -> b) -> a -> b
    $ [Int] -> [t] -> [(Int, t)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [Int]
    nbs [t]
    l)]
      where nbs :: [Int]
            nbs :: [Int]
    nbs = [Int
    0..]