    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE BangPatterns #-}
    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.Word
    import           Data.Bits
    import           Data.List

    -- 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 = 16

    mdsPolynomial, rsPolynomial :: Word32
    mdsPolynomial :: Word32
    mdsPolynomial = 0x169 -- x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
    rsPolynomial :: Word32
    rsPolynomial = 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
    /= :: ByteSize -> ByteSize -> Bool
    $c/= :: ByteSize -> ByteSize -> Bool
    == :: ByteSize -> ByteSize -> Bool
    $c== :: ByteSize -> ByteSize -> Bool
    Eq)

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

    buildPackage :: ByteArray ba => ba -> Maybe (KeyPackage ba)
    buildPackage :: ba -> Maybe (KeyPackage ba)
    buildPackage key :: ba
    key
        | ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length ba
    key Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 16 = KeyPackage ba -> Maybe (KeyPackage ba)
    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
    == 24 = KeyPackage ba -> Maybe (KeyPackage ba)
    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
    == 32 = KeyPackage ba -> Maybe (KeyPackage ba)
    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 :: key -> CryptoFailable Twofish
    initTwofish key :: key
    key =
        case key -> Maybe (KeyPackage key)
    forall ba. ByteArray ba => ba -> Maybe (KeyPackage ba)
    buildPackage key
    key of Nothing -> CryptoError -> CryptoFailable Twofish
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed CryptoError
    CryptoError_KeySizeInvalid
                                 Just keyPackage :: KeyPackage key
    keyPackage -> Twofish -> CryptoFailable Twofish
    forall a. a -> CryptoFailable a
    CryptoPassed Twofish :: (Array32, Array32, Array32, Array32) -> Array32 -> Twofish
    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 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 :: (ba -> ba) -> ba -> ba
    mapBlocks operation :: ba -> ba
    operation input :: 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 (block :: ba
    block, rest :: 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 :: Twofish -> ba -> ba
    encrypt cipher :: 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 :: Twofish -> ba -> ba
    encryptBlock Twofish { s :: Twofish -> (Array32, Array32, Array32, Array32)
    s = (s1 :: Array32
    s1, s2 :: Array32
    s2, s3 :: Array32
    s3, s4 :: Array32
    s4), k :: Twofish -> Array32
    k = Array32
    ks } message :: ba
    message = (Word32, Word32, Word32, Word32) -> ba
    forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls (Word32, Word32, Word32, Word32)
    ts
        where (a :: Word32
    a, b :: Word32
    b, c :: Word32
    c, d :: 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 0
              b' :: Word32
    b' = Word32
    b Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 1
              c' :: Word32
    c' = Word32
    c Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 2
              d' :: Word32
    d' = Word32
    d Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 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 (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') [0..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 4, Word32
    d'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 5, Word32
    a'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 6, Word32
    b'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 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) ind :: Int
    ind = (Word32
    retA', Word32
    retB', Word32
    retC', Word32
    retD')
                where [k0 :: Word32
    k0, k1 :: Word32
    k1, k2 :: Word32
    k2, k3 :: Word32
    k3] = (Int -> Word32) -> [Int] -> [Word32]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\offset :: Int
    offset -> Array32 -> Int -> Word32
    arrayRead32 Array32
    ks (Int -> Word32) -> Int -> Word32
    forall a b. (a -> b) -> a -> b
    $ (8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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) [0..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 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 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 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 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 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 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)) 1
                      retD' :: Word32
    retD' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retD 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' 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' 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' 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' 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' 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' 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)) 1
                      retB' :: Word32
    retB' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    retB 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 xs :: Array32
    xs ind :: 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` 256

    -- | Decrypts the given ByteString using the given Key
    decrypt :: ByteArray ba
            => Twofish     -- ^ The key to use
            -> ba           -- ^ The data to decrypt
            -> ba
    decrypt :: Twofish -> ba -> ba
    decrypt cipher :: 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 :: Twofish -> ba -> ba
    decryptBlock Twofish { s :: Twofish -> (Array32, Array32, Array32, Array32)
    s = (s1 :: Array32
    s1, s2 :: Array32
    s2, s3 :: Array32
    s3, s4 :: Array32
    s4), k :: Twofish -> Array32
    k = Array32
    ks } message :: ba
    message = (Word32, Word32, Word32, Word32) -> ba
    forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls (Word32, Word32, Word32, Word32)
    ixs
        where (a :: Word32
    a, b :: Word32
    b, c :: Word32
    c, d :: 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 6
              b' :: Word32
    b' = Word32
    d Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 7
              c' :: Word32
    c' = Word32
    a Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 4
              d' :: Word32
    d' = Word32
    b Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 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 (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') [8, 7..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 0, Word32
    b'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 1, Word32
    c'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 2, Word32
    d'' Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` Array32 -> Int -> Word32
    arrayRead32 Array32
    ks 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) ind :: Int
    ind = (Word32
    retA', Word32
    retB', Word32
    retC', Word32
    retD')
                where [k0 :: Word32
    k0, k1 :: Word32
    k1, k2 :: Word32
    k2, k3 :: Word32
    k3] = (Int -> Word32) -> [Int] -> [Word32]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\offset :: Int
    offset -> Array32 -> Int -> Word32
    arrayRead32 Array32
    ks (Int -> Word32) -> Int -> Word32
    forall a b. (a -> b) -> a -> b
    $ (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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) [0..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 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 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 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 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 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 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 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)) 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' 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' 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' 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' 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' 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' 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 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)) 1

    sbox0 :: Int -> Word8
    sbox0 :: Int -> Word8
    sbox0 = Array8 -> Int -> Word8
    arrayRead8 Array8
    t
        where t :: Array8
    t = Addr# -> Array8
    array8
                "\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
                "\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 = [ [0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E]
         , [0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5]
         , [0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19]
         , [0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03] ]

    load32ls :: ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
    load32ls :: ba -> (Word32, Word32, Word32, Word32)
    load32ls message :: 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 (half1 :: ba
    half1, half2 :: ba
    half2) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt 8 ba
    message
              (q1 :: ba
    q1, q2 :: ba
    q2) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt 4 ba
    half1
              (q3 :: ba
    q3, q4 :: ba
    q4) = Int -> ba -> (ba, ba)
    forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    B.splitAt 4 ba
    half2

              intify :: ByteArray ba => ba -> Word32
              intify :: ba -> Word32
    intify bytes :: ba
    bytes = (Word32 -> (Word8, Int) -> Word32)
    -> Word32 -> [(Word8, Int)] -> Word32
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (\int :: 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
    * 8) ) 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) [0..])

    store32ls :: ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
    store32ls :: (Word32, Word32, Word32, Word32) -> ba
    store32ls (a :: Word32
    a, b :: Word32
    b, c :: Word32
    c, d :: 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 w :: Word32
    w = (Int -> Word8) -> [Int] -> [Word8]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\ind :: 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 (8 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    ind)) [0..3]

    -- Create S words
    sWords :: ByteArray ba => ba -> [Word8]
    sWords :: ba -> [Word8]
    sWords key :: 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` 2
              sWord :: [Word8]
    sWord = (Int -> [Word8]) -> [Int] -> [Word8]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\wordIndex :: Int
    wordIndex ->
                            ([Word8] -> Word8) -> [[Word8]] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    map (\rsRow :: [Word8]
    rsRow ->
                                (Word8 -> (Word8, Int) -> Word8)
    -> Word8 -> [(Word8, Int)] -> Word8
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (\acc :: 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
    $ 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
                                    ) 0 ([Word8] -> [Int] -> [(Word8, Int)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [Word8]
    rsRow [0..])
                                ) [[Word8]]
    rs
                        ) [0..Int
    word64Count Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 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
    showList :: [Column] -> ShowS
    $cshowList :: [Column] -> ShowS
    show :: Column -> String
    $cshow :: Column -> String
    showsPrec :: Int -> Column -> ShowS
    $cshowsPrec :: Int -> Column -> ShowS
    Show, Column -> Column -> Bool
    (Column -> Column -> Bool)
    -> (Column -> Column -> Bool) -> Eq Column
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Column -> Column -> Bool
    $c/= :: Column -> Column -> Bool
    == :: Column -> Column -> Bool
    $c== :: 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
    enumFromThenTo :: Column -> Column -> Column -> [Column]
    $cenumFromThenTo :: Column -> Column -> Column -> [Column]
    enumFromTo :: Column -> Column -> [Column]
    $cenumFromTo :: Column -> Column -> [Column]
    enumFromThen :: Column -> Column -> [Column]
    $cenumFromThen :: Column -> Column -> [Column]
    enumFrom :: Column -> [Column]
    $cenumFrom :: Column -> [Column]
    fromEnum :: Column -> Int
    $cfromEnum :: Column -> Int
    toEnum :: Int -> Column
    $ctoEnum :: Int -> Column
    pred :: Column -> Column
    $cpred :: Column -> Column
    succ :: Column -> Column
    $csucc :: Column -> Column
    Enum, Column
    Column -> Column -> Bounded Column
    forall a. a -> a -> Bounded a
    maxBound :: Column
    $cmaxBound :: Column
    minBound :: Column
    $cminBound :: Column
    Bounded)

    genSboxes :: KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
    genSboxes :: KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
    genSboxes keyPackage :: KeyPackage ba
    keyPackage ws :: [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 = [0..255]
              mkArray :: [Word32] -> Array32
    mkArray = Int -> [Word32] -> Array32
    array32 256
              [w0 :: Word8
    w0, w1 :: Word8
    w1, w2 :: Word8
    w2, w3 :: Word8
    w3, w4 :: Word8
    w4, w5 :: Word8
    w5, w6 :: Word8
    w6, w7 :: Word8
    w7, w8 :: Word8
    w8, w9 :: Word8
    w9, w10 :: Word8
    w10, w11 :: Word8
    w11, w12 :: Word8
    w12, w13 :: Word8
    w13, w14 :: Word8
    w14, w15 :: Word8
    w15] = Int -> [Word8] -> [Word8]
    forall a. Int -> [a] -> [a]
    take 16 [Word8]
    ws
              (b0' :: [Word32]
    b0', b1' :: [Word32]
    b1', b2' :: [Word32]
    b2', b3' :: [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 Bytes16 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
                where !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    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 byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 Bytes24 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
                where !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 Bytes32 = ([Word32]
    b0, [Word32]
    b1, [Word32]
    b2, [Word32]
    b3)
                where !b0 :: [Word32]
    b0 = (Int -> Word32) -> [Int] -> [Word32]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Int -> Word32
    mapper [Int]
    range
                        where mapper :: Int -> Word32
    mapper byte :: 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 :: KeyPackage ba -> [Word32]
    genK keyPackage :: KeyPackage ba
    keyPackage = (Word8 -> [Word32]) -> [Word8] -> [Word32]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Word8 -> [Word32]
    makeTuple [0..19]
        where makeTuple :: Word8 -> [Word32]
              makeTuple :: Word8 -> [Word32]
    makeTuple idx :: 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 (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) 9]
                where tmp1 :: [Word8]
    tmp1 = Int -> Word8 -> [Word8]
    forall a. Int -> a -> [a]
    replicate 4 (Word8 -> [Word8]) -> Word8 -> [Word8]
    forall a b. (a -> b) -> a -> b
    $ 2 Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    * Word8
    idx
                      tmp2 :: [Word8]
    tmp2 = (Word8 -> Word8) -> [Word8] -> [Word8]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    +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 0
                      b :: Word32
    b = [Word8] -> KeyPackage ba -> Int -> Word32
    forall ba.
    ByteArray ba =>
    [Word8] -> KeyPackage ba -> Int -> Word32
    h [Word8]
    tmp2 KeyPackage ba
    keyPackage 1
                      b' :: Word32
    b' = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    b 8

    h :: (ByteArray ba) => [Word8] -> KeyPackage ba -> Int -> Word32
    h :: [Word8] -> KeyPackage ba -> Int -> Word32
    h input :: [Word8]
    input keyPackage :: KeyPackage ba
    keyPackage offset :: Int
    offset =  (Word32 -> (Word8, Column) -> Word32)
    -> Word32 -> [(Word8, Column)] -> Word32
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' Word32 -> (Word8, Column) -> Word32
    xorMdsColMult 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
              [y0 :: Word8
    y0, y1 :: Word8
    y1, y2 :: Word8
    y2, y3 :: Word8
    y3] = Int -> [Word8] -> [Word8]
    forall a. Int -> [a] -> [a]
    take 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'') 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (6 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 3)

              run (!Word8
    y0'', !Word8
    y1'', !Word8
    y2'', !Word8
    y3'') 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 3)

              run (!Word8
    y0'', !Word8
    y1'', !Word8
    y2'', !Word8
    y3'') 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 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 (4 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * (0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    offset) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 3)

              xorMdsColMult :: Word32 -> (Word8, Column) -> Word32
              xorMdsColMult :: Word32 -> (Word8, Column) -> Word32
    xorMdsColMult acc :: Word32
    acc wordAndIndex :: (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 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 8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF 16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF 24
                    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 8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mul5B 16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    input 24
                    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 8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    input 16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF 24
                    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 8 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mulEF 16 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    rotateL Word32
    mul5B 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 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 0xEF

    tupInd :: (Bits b) => b -> (a, a) -> a
    tupInd :: b -> (a, a) -> a
    tupInd b :: b
    b
        | b -> Int -> Bool
    forall a. Bits a => a -> Int -> Bool
    testBit b
    b 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 p :: Word32
    p a :: Word8
    a b :: 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 0
        where b' :: (Word32, Word32)
    b' = (0, Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    b)
              p' :: (Word32, Word32)
    p' = (0, Word32
    p)
              result :: Word32
    result = 0

              run :: Word8 -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
              run :: Word8
    -> (Word32, Word32) -> (Word32, Word32) -> Word32 -> Int -> Word32
    run a' :: Word8
    a' b'' :: (Word32, Word32)
    b'' p'' :: (Word32, Word32)
    p'' result' :: Word32
    result' count :: Int
    count =
                if Int
    count Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 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
    + 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
    .&. 1) (Word32, Word32)
    b''
                          a'' :: Word8
    a'' = Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    shiftR Word8
    a' 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'') 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'') 1)