    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE MagicHash #-}
    {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

    module Crypto.Cipher.Twofish.Primitive (
        Twofish,
        initTwofish,
        encrypt,
        decrypt,
    ) where

    import Crypto.Error
    import Crypto.Internal.ByteArray (ByteArray)
    import qualified Crypto.Internal.ByteArray as B
    import Crypto.Internal.WordArray
    import Data.Bits
    import Data.List (foldl')
    import Data.Word

    -- Based on the Golang referance implementation
    -- https://github.com/golang/crypto/blob/master/twofish/twofish.go

    -- BlockSize is the constant block size of Twofish.
    blockSize :: Int
    blockSize :: Int
    blockSize = Int
    16

    mdsPolynomial, rsPolynomial :: Word32
    mdsPolynomial :: Word32
    mdsPolynomial = Word32
    0x169 -- x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
    rsPolynomial :: Word32
    rsPolynomial = Word32
    0x14d -- x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3

    data Twofish = Twofish
        { Twofish -> (Array32, Array32, Array32, Array32)
    s :: (Array32, Array32, Array32, Array32)
        , Twofish -> Array32
    k :: Array32
        }

    data ByteSize = Bytes16 | Bytes24 | Bytes32 deriving (ByteSize -> ByteSize -> Bool
    (ByteSize -> ByteSize -> Bool)
    -> (ByteSize -> ByteSize -> Bool) -> Eq ByteSize
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ByteSize -> ByteSize -> Bool
    == :: ByteSize -> ByteSize -> Bool
    $c/= :: ByteSize -> ByteSize -> Bool
    /= :: ByteSize -> ByteSize -> Bool
    Eq)

    data KeyPackage ba = KeyPackage
        { forall ba. KeyPackage ba -> ba
    rawKeyBytes :: ba
        , forall ba. KeyPackage ba -> ByteSize
    byteSize :: ByteSize
        }

    buildPackage :: ByteArray ba => ba -> Maybe (KeyPackage ba)
    buildPackage :: forall ba. ByteArray ba => ba -> Maybe (KeyPackage ba)
    buildPackage ba
    key
        | ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    key Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    16 = KeyPackage ba -> Maybe (KeyPackage ba)
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (KeyPackage ba -> Maybe (KeyPackage ba))
    -> KeyPackage ba -> Maybe (KeyPackage ba)
    forall a b. (a -> b) -> a -> b
    $ ba -> ByteSize -> KeyPackage ba
    forall ba. ba -> ByteSize -> KeyPackage ba
    KeyPackage ba
    key ByteSize
    Bytes16
        | ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    key Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    24 = KeyPackage ba -> Maybe (KeyPackage ba)
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (KeyPackage ba -> Maybe (KeyPackage ba))
    -> KeyPackage ba -> Maybe (KeyPackage ba)
    forall a b. (a -> b) -> a -> b
    $ ba -> ByteSize -> KeyPackage ba
    forall ba. ba -> ByteSize -> KeyPackage ba
    KeyPackage ba
    key ByteSize
    Bytes24
        | ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    key Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    32 = KeyPackage ba -> Maybe (KeyPackage ba)
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (KeyPackage ba -> Maybe (KeyPackage ba))
    -> KeyPackage ba -> Maybe (KeyPackage ba)
    forall a b. (a -> b) -> a -> b
    $ ba -> ByteSize -> KeyPackage ba
    forall ba. ba -> ByteSize -> KeyPackage ba
    KeyPackage ba
    key ByteSize
    Bytes32
        | Bool
    otherwise = Maybe (KeyPackage ba)
    forall a. Maybe a
    Nothing

    -- | Initialize a 128-bit, 192-bit, or 256-bit key
    --
    -- Return the initialized key or a error message if the given
    -- keyseed was not 16-bytes in length.
    initTwofish
        :: ByteArray key
        => key
        -- ^ The key to create the twofish context
        -> CryptoFailable Twofish
    initTwofish :: forall key. ByteArray key => key -> CryptoFailable Twofish
    initTwofish key
    key =
        case key -> Maybe (KeyPackage key)
    forall ba. ByteArray ba => ba -> Maybe (KeyPackage ba)
    buildPackage key
    key of
            Maybe (KeyPackage key)
    Nothing -> CryptoError -> CryptoFailable Twofish
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_KeySizeInvalid
            Just KeyPackage key
    keyPackage -> Twofish -> CryptoFailable Twofish
    forall a. a -> CryptoFailable a
    CryptoPassed Twofish{k :: Array32
    k = Array32
    generatedK, s :: (Array32, Array32, Array32, Array32)
    s = (Array32, Array32, Array32, Array32)
    generatedS}
              where
                generatedK :: Array32
    generatedK = Int -> [Word32] -> Array32
    array32 Int
    40 ([Word32] -> Array32) -> [Word32] -> Array32
    forall a b. (a -> b) -> a -> b
    $ KeyPackage key -> [Word32]
    forall ba. ByteArray ba => KeyPackage ba -> [Word32]
    genK KeyPackage key
    keyPackage
                generatedS :: (Array32, Array32, Array32, Array32)
    generatedS = KeyPackage key -> [Word8] -> (Array32, Array32, Array32, Array32)
    forall ba.
    KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
    genSboxes KeyPackage key
    keyPackage ([Word8] -> (Array32, Array32, Array32, Array32))
    -> [Word8] -> (Array32, Array32, Array32, Array32)
    forall a b. (a -> b) -> a -> b
    $ key -> [Word8]
    forall ba. ByteArray ba => ba -> [Word8]
    sWords key
    key

    mapBlocks :: ByteArray ba => (ba -> ba) -> ba -> ba
    mapBlocks :: forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
    mapBlocks ba -> ba
    operation ba
    input
        | ba -> Bool
    forall a. ByteArrayAccess a => a -> Bool
    B.null ba
    rest = ba
    blockOutput
        | Bool
    otherwise = ba
    blockOutput ba -> ba -> ba
    forall bs. ByteArray bs => bs -> bs -> bs
    `B.append` (ba -> ba) -> ba -> ba
    forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
    mapBlocks ba -> ba
    operation ba
    rest
      where
        (ba
    block, ba
    rest) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt Int
    blockSize ba
    input
        blockOutput :: ba
    blockOutput = ba -> ba
    operation ba
    block

    -- | Encrypts the given ByteString using the given Key
    encrypt
        :: ByteArray ba
        => Twofish
        -- ^ The key to use
        -> ba
        -- ^ The data to encrypt
        -> ba
    encrypt :: forall ba. ByteArray ba => Twofish -> ba -> ba
    encrypt Twofish
    cipher = (ba -> ba) -> ba -> ba
    forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
    mapBlocks (Twofish -> ba -> ba
    forall ba. ByteArray ba => Twofish -> ba -> ba
    encryptBlock Twofish
    cipher)

    encryptBlock :: ByteArray ba => Twofish -> ba -> ba
    encryptBlock :: forall ba. ByteArray ba => Twofish -> ba -> ba
    encryptBlock Twofish{s :: Twofish -> (Array32, Array32, Array32, Array32)
    s = (Array32
    s1, Array32
    s2, Array32
    s3, Array32
    s4), k :: Twofish -> Array32
    k = Array32
    ks} ba
    message = (Word32, Word32, Word32, Word32) -> ba
    forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls (Word32, Word32, Word32, Word32)
    ts
      where
        (Word32
    a, Word32
    b, Word32
    c, Word32
    d) = ba -> (Word32, Word32, Word32, Word32)
    forall ba. ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
    load32ls ba
    message
        a' :: Word32
    a' = Word32
    a Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    0
        b' :: Word32
    b' = Word32
    b Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    1
        c' :: Word32
    c' = Word32
    c Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    2
        d' :: Word32
    d' = Word32
    d Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    3
        (!Word32
    a'', !Word32
    b'', !Word32
    c'', !Word32
    d'') = ((Word32, Word32, Word32, Word32)
     -> Int -> (Word32, Word32, Word32, Word32))
    -> (Word32, Word32, Word32, Word32)
    -> [Int]
    -> (Word32, Word32, Word32, Word32)
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (Word32, Word32, Word32, Word32)
    -> Int -> (Word32, Word32, Word32, Word32)
    shuffle (Word32
    a', Word32
    b', Word32
    c', Word32
    d') [Int
    0 .. Int
    7]
        ts :: (Word32, Word32, Word32, Word32)
    ts =
            ( Word32
    c'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    4
            , Word32
    d'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    5
            , Word32
    a'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    6
            , Word32
    b'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    7
            )

        shuffle
            :: (Word32, Word32, Word32, Word32) -> Int -> (Word32, Word32, Word32, Word32)
        shuffle :: (Word32, Word32, Word32, Word32)
    -> Int -> (Word32, Word32, Word32, Word32)
    shuffle (!Word32
    retA, !Word32
    retB, !Word32
    retC, !Word32
    retD) Int
    ind = (Word32
    retA', Word32
    retB', Word32
    retC', Word32
    retD')
          where
            [Word32
    k0, Word32
    k1, Word32
    k2, Word32
    k3] = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\Int
    offset -> Array32 -> Int -> Word32
    arrayRead32 Array32
    ks (Int -> Word32) -> Int -> Word32
    forall a b. (a -> b) -> a -> b
    $ (Int
    8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    ind) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) [Int
    0 .. Int
    3]
            t2 :: Word32
    t2 =
                Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 Word32
    retB
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB Int
    24)
            t1 :: Word32
    t1 =
                ( Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 Word32
    retA
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA Int
    24)
                )
                    Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2
            retC' :: Word32
    retC' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateR (Word32
    retC Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k0)) Int
    1
            retD' :: Word32
    retD' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retD Int
    1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k1)
            t2' :: Word32
    t2' =
                Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 Word32
    retD'
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD' Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD' Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD' Int
    24)
            t1' :: Word32
    t1' =
                ( Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 Word32
    retC'
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC' Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC' Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC' Int
    24)
                )
                    Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2'
            retA' :: Word32
    retA' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateR (Word32
    retA Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k2)) Int
    1
            retB' :: Word32
    retB' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retB Int
    1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k3)

    -- Unsafe, no bounds checking
    byteIndex :: Array32 -> Word32 -> Word32
    byteIndex :: Array32 -> Word32 -> Word32
    byteIndex Array32
    xs Word32
    ind = Array32 -> Int -> Word32
    arrayRead32 Array32
    xs (Int -> Word32) -> Int -> Word32
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    byte
      where
        byte :: Word32
    byte = Word32
    ind Word32 -> Word32 -> Word32
    forall a. Integral a => a -> a -> a
    `mod` Word32
    256

    -- | Decrypts the given ByteString using the given Key
    decrypt
        :: ByteArray ba
        => Twofish
        -- ^ The key to use
        -> ba
        -- ^ The data to decrypt
        -> ba
    decrypt :: forall ba. ByteArray ba => Twofish -> ba -> ba
    decrypt Twofish
    cipher = (ba -> ba) -> ba -> ba
    forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
    mapBlocks (Twofish -> ba -> ba
    forall ba. ByteArray ba => Twofish -> ba -> ba
    decryptBlock Twofish
    cipher)

    {- decryption for 128 bits blocks -}
    decryptBlock :: ByteArray ba => Twofish -> ba -> ba
    decryptBlock :: forall ba. ByteArray ba => Twofish -> ba -> ba
    decryptBlock Twofish{s :: Twofish -> (Array32, Array32, Array32, Array32)
    s = (Array32
    s1, Array32
    s2, Array32
    s3, Array32
    s4), k :: Twofish -> Array32
    k = Array32
    ks} ba
    message = (Word32, Word32, Word32, Word32) -> ba
    forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls (Word32, Word32, Word32, Word32)
    ixs
      where
        (Word32
    a, Word32
    b, Word32
    c, Word32
    d) = ba -> (Word32, Word32, Word32, Word32)
    forall ba. ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
    load32ls ba
    message
        a' :: Word32
    a' = Word32
    c Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    6
        b' :: Word32
    b' = Word32
    d Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    7
        c' :: Word32
    c' = Word32
    a Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    4
        d' :: Word32
    d' = Word32
    b Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    5
        (!Word32
    a'', !Word32
    b'', !Word32
    c'', !Word32
    d'') = ((Word32, Word32, Word32, Word32)
     -> Int -> (Word32, Word32, Word32, Word32))
    -> (Word32, Word32, Word32, Word32)
    -> [Int]
    -> (Word32, Word32, Word32, Word32)
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (Word32, Word32, Word32, Word32)
    -> Int -> (Word32, Word32, Word32, Word32)
    unshuffle (Word32
    a', Word32
    b', Word32
    c', Word32
    d') [Int
    8, Int
    7 .. Int
    1]
        ixs :: (Word32, Word32, Word32, Word32)
    ixs =
            ( Word32
    a'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    0
            , Word32
    b'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    1
            , Word32
    c'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    2
            , Word32
    d'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks Int
    3
            )

        unshuffle
            :: (Word32, Word32, Word32, Word32) -> Int -> (Word32, Word32, Word32, Word32)
        unshuffle :: (Word32, Word32, Word32, Word32)
    -> Int -> (Word32, Word32, Word32, Word32)
    unshuffle (!Word32
    retA, !Word32
    retB, !Word32
    retC, !Word32
    retD) Int
    ind = (Word32
    retA', Word32
    retB', Word32
    retC', Word32
    retD')
          where
            [Word32
    k0, Word32
    k1, Word32
    k2, Word32
    k3] = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\Int
    offset -> Array32 -> Int -> Word32
    arrayRead32 Array32
    ks (Int -> Word32) -> Int -> Word32
    forall a b. (a -> b) -> a -> b
    $ (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    ind) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) [Int
    0 .. Int
    3]
            t2 :: Word32
    t2 =
                Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 Word32
    retD
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retD Int
    24)
            t1 :: Word32
    t1 =
                ( Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 Word32
    retC
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retC Int
    24)
                )
                    Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2
            retA' :: Word32
    retA' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retA Int
    1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k2)
            retB' :: Word32
    retB' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateR (Word32
    retB Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t2 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t1 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k3)) Int
    1
            t2' :: Word32
    t2' =
                Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 Word32
    retB'
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB' Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB' Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retB' Int
    24)
            t1' :: Word32
    t1' =
                ( Array32 -> Word32 -> Word32
    byteIndex Array32
    s1 Word32
    retA'
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s2 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA' Int
    8)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s3 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA' Int
    16)
                    Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Word32 -> Word32
    byteIndex Array32
    s4 (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    retA' Int
    24)
                )
                    Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t2'
            retC' :: Word32
    retC' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retC Int
    1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t1' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k0)
            retD' :: Word32
    retD' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateR (Word32
    retD Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    t2' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    t1' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    k1)) Int
    1

    sbox0 :: Int -> Word8
    sbox0 :: Int -> Word8
    sbox0 = Array8 -> Int -> Word8
    arrayRead8 Array8
    t
      where
        t :: Array8
    t =
            Addr# -> Array8
    array8
                Addr#
    "\xa9\x67\xb3\xe8\x04\xfd\xa3\x76\x9a\x92\x80\x78\xe4\xdd\xd1\x38\
                \\x0d\xc6\x35\x98\x18\xf7\xec\x6c\x43\x75\x37\x26\xfa\x13\x94\x48\
                \\xf2\xd0\x8b\x30\x84\x54\xdf\x23\x19\x5b\x3d\x59\xf3\xae\xa2\x82\
                \\x63\x01\x83\x2e\xd9\x51\x9b\x7c\xa6\xeb\xa5\xbe\x16\x0c\xe3\x61\
                \\xc0\x8c\x3a\xf5\x73\x2c\x25\x0b\xbb\x4e\x89\x6b\x53\x6a\xb4\xf1\
                \\xe1\xe6\xbd\x45\xe2\xf4\xb6\x66\xcc\x95\x03\x56\xd4\x1c\x1e\xd7\
                \\xfb\xc3\x8e\xb5\xe9\xcf\xbf\xba\xea\x77\x39\xaf\x33\xc9\x62\x71\
                \\x81\x79\x09\xad\x24\xcd\xf9\xd8\xe5\xc5\xb9\x4d\x44\x08\x86\xe7\
                \\xa1\x1d\xaa\xed\x06\x70\xb2\xd2\x41\x7b\xa0\x11\x31\xc2\x27\x90\
                \\x20\xf6\x60\xff\x96\x5c\xb1\xab\x9e\x9c\x52\x1b\x5f\x93\x0a\xef\
                \\x91\x85\x49\xee\x2d\x4f\x8f\x3b\x47\x87\x6d\x46\xd6\x3e\x69\x64\
                \\x2a\xce\xcb\x2f\xfc\x97\x05\x7a\xac\x7f\xd5\x1a\x4b\x0e\xa7\x5a\
                \\x28\x14\x3f\x29\x88\x3c\x4c\x02\xb8\xda\xb0\x17\x55\x1f\x8a\x7d\
                \\x57\xc7\x8d\x74\xb7\xc4\x9f\x72\x7e\x15\x22\x12\x58\x07\x99\x34\
                \\x6e\x50\xde\x68\x65\xbc\xdb\xf8\xc8\xa8\x2b\x40\xdc\xfe\x32\xa4\
                \\xca\x10\x21\xf0\xd3\x5d\x0f\x00\x6f\x9d\x36\x42\x4a\x5e\xc1\xe0"#

    sbox1 :: Int -> Word8
    sbox1 :: Int -> Word8
    sbox1 = Array8 -> Int -> Word8
    arrayRead8 Array8
    t
      where
        t :: Array8
    t =
            Addr# -> Array8
    array8
                Addr#
    "\x75\xf3\xc6\xf4\xdb\x7b\xfb\xc8\x4a\xd3\xe6\x6b\x45\x7d\xe8\x4b\
                \\xd6\x32\xd8\xfd\x37\x71\xf1\xe1\x30\x0f\xf8\x1b\x87\xfa\x06\x3f\
                \\x5e\xba\xae\x5b\x8a\x00\xbc\x9d\x6d\xc1\xb1\x0e\x80\x5d\xd2\xd5\
                \\xa0\x84\x07\x14\xb5\x90\x2c\xa3\xb2\x73\x4c\x54\x92\x74\x36\x51\
                \\x38\xb0\xbd\x5a\xfc\x60\x62\x96\x6c\x42\xf7\x10\x7c\x28\x27\x8c\
                \\x13\x95\x9c\xc7\x24\x46\x3b\x70\xca\xe3\x85\xcb\x11\xd0\x93\xb8\
                \\xa6\x83\x20\xff\x9f\x77\xc3\xcc\x03\x6f\x08\xbf\x40\xe7\x2b\xe2\
                \\x79\x0c\xaa\x82\x41\x3a\xea\xb9\xe4\x9a\xa4\x97\x7e\xda\x7a\x17\
                \\x66\x94\xa1\x1d\x3d\xf0\xde\xb3\x0b\x72\xa7\x1c\xef\xd1\x53\x3e\
                \\x8f\x33\x26\x5f\xec\x76\x2a\x49\x81\x88\xee\x21\xc4\x1a\xeb\xd9\
                \\xc5\x39\x99\xcd\xad\x31\x8b\x01\x18\x23\xdd\x1f\x4e\x2d\xf9\x48\
                \\x4f\xf2\x65\x8e\x78\x5c\x58\x19\x8d\xe5\x98\x57\x67\x7f\x05\x64\
                \\xaf\x63\xb6\xfe\xf5\xb7\x3c\xa5\xce\xe9\x68\x44\xe0\x4d\x43\x69\
                \\x29\x2e\xac\x15\x59\xa8\x0a\x9e\x6e\x47\xdf\x34\x35\x6a\xcf\xdc\
                \\x22\xc9\xc0\x9b\x89\xd4\xed\xab\x12\xa2\x0d\x52\xbb\x02\x2f\xa9\
                \\xd7\x61\x1e\xb4\x50\x04\xf6\xc2\x16\x25\x86\x56\x55\x09\xbe\x91"#

    rs :: [[Word8]]
    rs :: [[Word8]]
    rs =
        [ [Word8
    0x01, Word8
    0xA4, Word8
    0x55, Word8
    0x87, Word8
    0x5A, Word8
    0x58, Word8
    0xDB, Word8
    0x9E]
        , [Word8
    0xA4, Word8
    0x56, Word8
    0x82, Word8
    0xF3, Word8
    0x1E, Word8
    0xC6, Word8
    0x68, Word8
    0xE5]
        , [Word8
    0x02, Word8
    0xA1, Word8
    0xFC, Word8
    0xC1, Word8
    0x47, Word8
    0xAE, Word8
    0x3D, Word8
    0x19]
        , [Word8
    0xA4, Word8
    0x55, Word8
    0x87, Word8
    0x5A, Word8
    0x58, Word8
    0xDB, Word8
    0x9E, Word8
    0x03]
        ]

    load32ls :: ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
    load32ls :: forall ba. ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
    load32ls ba
    message = (ba -> Word32
    forall ba. ByteArray ba => ba -> Word32
    intify ba
    q1, ba -> Word32
    forall ba. ByteArray ba => ba -> Word32
    intify ba
    q2, ba -> Word32
    forall ba. ByteArray ba => ba -> Word32
    intify ba
    q3, ba -> Word32
    forall ba. ByteArray ba => ba -> Word32
    intify ba
    q4)
      where
        (ba
    half1, ba
    half2) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt Int
    8 ba
    message
        (ba
    q1, ba
    q2) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt Int
    4 ba
    half1
        (ba
    q3, ba
    q4) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt Int
    4 ba
    half2

        intify :: ByteArray ba => ba -> Word32
        intify :: forall ba. ByteArray ba => ba -> Word32
    intify ba
    bytes =
            (Word32 -> (Word8, Int) -> Word32)
    -> Word32 -> [(Word8, Int)] -> Word32
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl'
                (\Word32
    int (!Word8
    word, !Int
    ind) -> Word32
    int Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftL (Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    word) (Int
    ind Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    8))
                Word32
    0
                ([Word8] -> [Int] -> [(Word8, Int)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip (ba -> [Word8]
    forall a. ByteArrayAccess a => a -> [Word8]
    B.unpack ba
    bytes) [Int
    0 ..])

    store32ls :: ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls :: forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls (Word32
    a, Word32
    b, Word32
    c, Word32
    d) = [Word8] -> ba
    forall a. ByteArray a => [Word8] -> a
    B.pack ([Word8] -> ba) -> [Word8] -> ba
    forall a b. (a -> b) -> a -> b
    $ (Word32 -> [Word8]) -> [Word32] -> [Word8]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Word32 -> [Word8]
    splitWordl [Word32
    a, Word32
    b, Word32
    c, Word32
    d]
      where
        splitWordl :: Word32 -> [Word8]
        splitWordl :: Word32 -> [Word8]
    splitWordl Word32
    w = (Int -> Word8) -> [Int] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\Int
    ind -> Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR Word32
    w (Int
    8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    ind)) [Int
    0 .. Int
    3]

    -- Create S words
    sWords :: ByteArray ba => ba -> [Word8]
    sWords :: forall ba. ByteArray ba => ba -> [Word8]
    sWords ba
    key = [Word8]
    sWord
      where
        word64Count :: Int
    word64Count = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    key Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    2
        sWord :: [Word8]
    sWord =
            (Int -> [Word8]) -> [Int] -> [Word8]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap
                ( \Int
    wordIndex ->
                    ([Word8] -> Word8) -> [[Word8]] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    map
                        ( \[Word8]
    rsRow ->
                            (Word8 -> (Word8, Int) -> Word8)
    -> Word8 -> [(Word8, Int)] -> Word8
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl'
                                ( \Word8
    acc (!Word8
    rsVal, !Int
    colIndex) ->
                                    Word8
    acc Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word32 -> Word8 -> Word8 -> Word8
    gfMult Word32
    rsPolynomial (ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int -> Word8) -> Int -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int
    8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    wordIndex Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    colIndex) Word8
    rsVal
                                )
                                Word8
    0
                                ([Word8] -> [Int] -> [(Word8, Int)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [Word8]
    rsRow [Int
    0 ..])
                        )
                        [[Word8]]
    rs
                )
                [Int
    0 .. Int
    word64Count Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1]

    data Column = Zero | One | Two | Three deriving (Int -> Column -> ShowS
    [Column] -> ShowS
    Column -> String
    (Int -> Column -> ShowS)
    -> (Column -> String) -> ([Column] -> ShowS) -> Show Column
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Column -> ShowS
    showsPrec :: Int -> Column -> ShowS
    $cshow :: Column -> String
    show :: Column -> String
    $cshowList :: [Column] -> ShowS
    showList :: [Column] -> ShowS
    Show, Column -> Column -> Bool
    (Column -> Column -> Bool)
    -> (Column -> Column -> Bool) -> Eq Column
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Column -> Column -> Bool
    == :: Column -> Column -> Bool
    $c/= :: Column -> Column -> Bool
    /= :: Column -> Column -> Bool
    Eq, Int -> Column
    Column -> Int
    Column -> [Column]
    Column -> Column
    Column -> Column -> [Column]
    Column -> Column -> Column -> [Column]
    (Column -> Column)
    -> (Column -> Column)
    -> (Int -> Column)
    -> (Column -> Int)
    -> (Column -> [Column])
    -> (Column -> Column -> [Column])
    -> (Column -> Column -> [Column])
    -> (Column -> Column -> Column -> [Column])
    -> Enum Column
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    $csucc :: Column -> Column
    succ :: Column -> Column
    $cpred :: Column -> Column
    pred :: Column -> Column
    $ctoEnum :: Int -> Column
    toEnum :: Int -> Column
    $cfromEnum :: Column -> Int
    fromEnum :: Column -> Int
    $cenumFrom :: Column -> [Column]
    enumFrom :: Column -> [Column]
    $cenumFromThen :: Column -> Column -> [Column]
    enumFromThen :: Column -> Column -> [Column]
    $cenumFromTo :: Column -> Column -> [Column]
    enumFromTo :: Column -> Column -> [Column]
    $cenumFromThenTo :: Column -> Column -> Column -> [Column]
    enumFromThenTo :: Column -> Column -> Column -> [Column]
    Enum, Column
    Column -> Column -> Bounded Column
    forall a. a -> a -> Bounded a
    $cminBound :: Column
    minBound :: Column
    $cmaxBound :: Column
    maxBound :: Column
    Bounded)

    genSboxes :: KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
    genSboxes :: forall ba.
    KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
    genSboxes KeyPackage ba
    keyPackage [Word8]
    ws = ([Word32] -> Array32
    mkArray [Word32]
    b0', [Word32] -> Array32
    mkArray [Word32]
    b1', [Word32] -> Array32
    mkArray [Word32]
    b2', [Word32] -> Array32
    mkArray [Word32]
    b3')
      where
        range :: [Int]
    range = [Int
    0 .. Int
    255]
        mkArray :: [Word32] -> Array32
    mkArray = Int -> [Word32] -> Array32
    array32 Int
    256
        [Word8
    w0, Word8
    w1, Word8
    w2, Word8
    w3, Word8
    w4, Word8
    w5, Word8
    w6, Word8
    w7, Word8
    w8, Word8
    w9, Word8
    w10, Word8
    w11, Word8
    w12, Word8
    w13, Word8
    w14, Word8
    w15] = Int -> [Word8] -> [Word8]
    forall a. Int -> [a] -> [a]
    take Int
    16 [Word8]
    ws
        ([Word32]
    b0', [Word32]
    b1', [Word32]
    b2', [Word32]
    b3') = ByteSize -> ([Word32], [Word32], [Word32], [Word32])
    sboxBySize (ByteSize -> ([Word32], [Word32], [Word32], [Word32]))
    -> ByteSize -> ([Word32], [Word32], [Word32], [Word32])
    forall a b. (a -> b) -> a -> b
    $ KeyPackage ba -> ByteSize
    forall ba. KeyPackage ba -> ByteSize
    byteSize KeyPackage ba
    keyPackage

        sboxBySize :: ByteSize -> ([Word32], [Word32], [Word32], [Word32])
        sboxBySize :: ByteSize -> ([Word32], [Word32], [Word32], [Word32])
    sboxBySize ByteSize
    Bytes16 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
          where
            !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w0) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w4))
                        Column
    Zero
            !b1 :: [Word32]
    b1 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w1) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w5))
                        Column
    One
            !b2 :: [Word32]
    b2 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w2) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w6))
                        Column
    Two
            !b3 :: [Word32]
    b3 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w3) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w7))
                        Column
    Three
        sboxBySize ByteSize
    Bytes24 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
          where
            !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w0) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w4)
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w8
                            )
                        )
                        Column
    Zero
            !b1 :: [Word32]
    b1 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w1) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w5)
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w9
                            )
                        )
                        Column
    One
            !b2 :: [Word32]
    b2 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w2) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w6)
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w10
                            )
                        )
                        Column
    Two
            !b3 :: [Word32]
    b3 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w3) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w7)
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w11
                            )
                        )
                        Column
    Three
        sboxBySize ByteSize
    Bytes32 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
          where
            !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                                ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w0) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w4)
                                    Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w8
                                )
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w12
                            )
                        )
                        Column
    Zero
            !b1 :: [Word32]
    b1 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                                ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w1) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w5)
                                    Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w9
                                )
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w13
                            )
                        )
                        Column
    One
            !b2 :: [Word32]
    b2 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                                ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox0 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w2) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w6)
                                    Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w10
                                )
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w14
                            )
                        )
                        Column
    Two
            !b3 :: [Word32]
    b3 = (Int -> Word32) -> [Int] -> [Word32]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
              where
                mapper :: Int -> Word32
    mapper Int
    byte =
                    Word8 -> Column -> Word32
    mdsColumnMult
                        ( (Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                            ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
                                ( (Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral) ((Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Int -> Word8
    sbox1 Int
    byte Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w3) Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w7)
                                    Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w11
                                )
                                Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    w15
                            )
                        )
                        Column
    Three

    genK :: ByteArray ba => KeyPackage ba -> [Word32]
    genK :: forall ba. ByteArray ba => KeyPackage ba -> [Word32]
    genK KeyPackage ba
    keyPackage = (Word8 -> [Word32]) -> [Word8] -> [Word32]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Word8 -> [Word32]
    makeTuple [Word8
    0 .. Word8
    19]
      where
        makeTuple :: Word8 -> [Word32]
        makeTuple :: Word8 -> [Word32]
    makeTuple Word8
    idx = [Word32
    a Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    b', Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL (Word32
    2 Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    * Word32
    b' Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    + Word32
    a) Int
    9]
          where
            tmp1 :: [Word8]
    tmp1 = Int -> Word8 -> [Word8]
    forall a. Int -> a -> [a]
    replicate Int
    4 (Word8 -> [Word8]) -> Word8 -> [Word8]
    forall a b. (a -> b) -> a -> b
    $ Word8
    2 Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    * Word8
    idx
            tmp2 :: [Word8]
    tmp2 = (Word8 -> Word8) -> [Word8] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Word8
    1) [Word8]
    tmp1
            a :: Word32
    a = [Word8] -> KeyPackage ba -> Int -> Word32
    forall ba.
    ByteArray ba =>
    [Word8] -> KeyPackage ba -> Int -> Word32
    h [Word8]
    tmp1 KeyPackage ba
    keyPackage Int
    0
            b :: Word32
    b = [Word8] -> KeyPackage ba -> Int -> Word32
    forall ba.
    ByteArray ba =>
    [Word8] -> KeyPackage ba -> Int -> Word32
    h [Word8]
    tmp2 KeyPackage ba
    keyPackage Int
    1
            b' :: Word32
    b' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    b Int
    8

    h :: ByteArray ba => [Word8] -> KeyPackage ba -> Int -> Word32
    h :: forall ba.
    ByteArray ba =>
    [Word8] -> KeyPackage ba -> Int -> Word32
    h [Word8]
    input KeyPackage ba
    keyPackage Int
    offset = (Word32 -> (Word8, Column) -> Word32)
    -> Word32 -> [(Word8, Column)] -> Word32
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' Word32 -> (Word8, Column) -> Word32
    xorMdsColMult Word32
    0 ([(Word8, Column)] -> Word32) -> [(Word8, Column)] -> Word32
    forall a b. (a -> b) -> a -> b
    $ [Word8] -> [Column] -> [(Word8, Column)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [Word8
    y0f, Word8
    y1f, Word8
    y2f, Word8
    y3f] ([Column] -> [(Word8, Column)]) -> [Column] -> [(Word8, Column)]
    forall a b. (a -> b) -> a -> b
    $ Column -> [Column]
    forall a. Enum a => a -> [a]
    enumFrom Column
    Zero
      where
        key :: ba
    key = KeyPackage ba -> ba
    forall ba. KeyPackage ba -> ba
    rawKeyBytes KeyPackage ba
    keyPackage
        [Word8
    y0, Word8
    y1, Word8
    y2, Word8
    y3] = Int -> [Word8] -> [Word8]
    forall a. Int -> [a] -> [a]
    take Int
    4 [Word8]
    input
        (!Word8
    y0f, !Word8
    y1f, !Word8
    y2f, !Word8
    y3f) = (Word8, Word8, Word8, Word8)
    -> ByteSize -> (Word8, Word8, Word8, Word8)
    run (Word8
    y0, Word8
    y1, Word8
    y2, Word8
    y3) (ByteSize -> (Word8, Word8, Word8, Word8))
    -> ByteSize -> (Word8, Word8, Word8, Word8)
    forall a b. (a -> b) -> a -> b
    $ KeyPackage ba -> ByteSize
    forall ba. KeyPackage ba -> ByteSize
    byteSize KeyPackage ba
    keyPackage

        run :: (Word8, Word8, Word8, Word8) -> ByteSize -> (Word8, Word8, Word8, Word8)
        run :: (Word8, Word8, Word8, Word8)
    -> ByteSize -> (Word8, Word8, Word8, Word8)
    run (!Word8
    y0'', !Word8
    y1'', !Word8
    y2'', !Word8
    y3'') ByteSize
    Bytes32 = (Word8, Word8, Word8, Word8)
    -> ByteSize -> (Word8, Word8, Word8, Word8)
    run (Word8
    y0', Word8
    y1', Word8
    y2', Word8
    y3') ByteSize
    Bytes24
          where
            y0' :: Word8
    y0' = Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y0'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    0)
            y1' :: Word8
    y1' = Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y1'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1)
            y2' :: Word8
    y2' = Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y2'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2)
            y3' :: Word8
    y3' = Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y3'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3)
        run (!Word8
    y0'', !Word8
    y1'', !Word8
    y2'', !Word8
    y3'') ByteSize
    Bytes24 = (Word8, Word8, Word8, Word8)
    -> ByteSize -> (Word8, Word8, Word8, Word8)
    run (Word8
    y0', Word8
    y1', Word8
    y2', Word8
    y3') ByteSize
    Bytes16
          where
            y0' :: Word8
    y0' = Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y0'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    0)
            y1' :: Word8
    y1' = Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y1'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1)
            y2' :: Word8
    y2' = Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y2'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2)
            y3' :: Word8
    y3' = Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y3'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3)
        run (!Word8
    y0'', !Word8
    y1'', !Word8
    y2'', !Word8
    y3'') ByteSize
    Bytes16 = (Word8
    y0', Word8
    y1', Word8
    y2', Word8
    y3')
          where
            y0' :: Word8
    y0' =
                Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                    ( Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                        (Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y0'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    0))
                    )
                        Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    0)
            y1' :: Word8
    y1' =
                Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                    ( Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                        (Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y1'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1))
                    )
                        Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1)
            y2' :: Word8
    y2' =
                Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                    ( Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                        (Int -> Word8
    sbox0 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y2'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2))
                    )
                        Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2)
            y3' :: Word8
    y3' =
                Int -> Word8
    sbox0 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                    ( Int -> Word8
    sbox1 (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word8) -> Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $
                        (Int -> Word8
    sbox1 (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y3'') Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3))
                    )
                        Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` ba -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    B.index ba
    key (Int
    4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (Int
    0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    3)

        xorMdsColMult :: Word32 -> (Word8, Column) -> Word32
        xorMdsColMult :: Word32 -> (Word8, Column) -> Word32
    xorMdsColMult Word32
    acc (Word8, Column)
    wordAndIndex = Word32
    acc Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word8 -> Column -> Word32) -> (Word8, Column) -> Word32
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Word8 -> Column -> Word32
    mdsColumnMult (Word8, Column)
    wordAndIndex

    mdsColumnMult :: Word8 -> Column -> Word32
    mdsColumnMult :: Word8 -> Column -> Word32
    mdsColumnMult !Word8
    byte !Column
    col =
        case Column
    col of
            Column
    Zero -> Word32
    input Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mul5B Int
    8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    24
            Column
    One -> Word32
    mulEF Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mul5B Int
    16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    input Int
    24
            Column
    Two -> Word32
    mul5B Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    input Int
    16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    24
            Column
    Three -> Word32
    mul5B Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    input Int
    8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF Int
    16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mul5B Int
    24
      where
        input :: Word32
    input = Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    byte
        mul5B :: Word32
    mul5B = Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word32) -> Word8 -> Word32
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Word8 -> Word8 -> Word8
    gfMult Word32
    mdsPolynomial Word8
    byte Word8
    0x5B
        mulEF :: Word32
    mulEF = Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> Word32) -> Word8 -> Word32
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Word8 -> Word8 -> Word8
    gfMult Word32
    mdsPolynomial Word8
    byte Word8
    0xEF

    tupInd :: Bits b => b -> (a, a) -> a
    tupInd :: forall b a. Bits b => b -> (a, a) -> a
    tupInd b
    b
        | b -> Int -> Bool
    forall a. Bits a => a -> Int -> Bool
    testBit b
    b Int
    0 = (a, a) -> a
    forall a b. (a, b) -> b
    snd
        | Bool
    otherwise = (a, a) -> a
    forall a b. (a, b) -> a
    fst

    gfMult :: Word32 -> Word8 -> Word8 -> Word8
    gfMult :: Word32 -> Word8 -> Word8 -> Word8
    gfMult Word32
    p Word8
    a Word8
    b = Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word8
    -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
    run Word8
    a (Word32, Word32)
    b' (Word32, Word32)
    p' Word32
    result Int
    0
      where
        b' :: (Word32, Word32)
    b' = (Word32
    0, Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    b)
        p' :: (Word32, Word32)
    p' = (Word32
    0, Word32
    p)
        result :: Word32
    result = Word32
    0

        run :: Word8 -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
        run :: Word8
    -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
    run Word8
    a' (Word32, Word32)
    b'' (Word32, Word32)
    p'' Word32
    result' Int
    count =
            if Int
    count Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    7
                then Word32
    result''
                else Word8
    -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
    run Word8
    a'' (Word32, Word32)
    b''' (Word32, Word32)
    p'' Word32
    result'' (Int
    count Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1)
          where
            result'' :: Word32
    result'' = Word32
    result' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Word8 -> (Word32, Word32) -> Word32
    forall b a. Bits b => b -> (a, a) -> a
    tupInd (Word8
    a' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    .&. Word8
    1) (Word32, Word32)
    b''
            a'' :: Word8
    a'' = Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    shiftR Word8
    a' Int
    1
            b''' :: (Word32, Word32)
    b''' = ((Word32, Word32) -> Word32
    forall a b. (a, b) -> a
    fst (Word32, Word32)
    b'', Word32 -> (Word32, Word32) -> Word32
    forall b a. Bits b => b -> (a, a) -> a
    tupInd (Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftR ((Word32, Word32) -> Word32
    forall a b. (a, b) -> b
    snd (Word32, Word32)
    b'') Int
    7) (Word32, Word32)
    p'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shiftL ((Word32, Word32) -> Word32
    forall a b. (a, b) -> b
    snd (Word32, Word32)
    b'') Int
    1)