{-# 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 = 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)