{-# 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
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 { 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
    | forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
key forall a. Eq a => a -> a -> Bool
== Int
16 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall ba. ba -> ByteSize -> KeyPackage ba
KeyPackage ba
key ByteSize
Bytes16
    | forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
key forall a. Eq a => a -> a -> Bool
== Int
24 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall ba. ba -> ByteSize -> KeyPackage ba
KeyPackage ba
key ByteSize
Bytes24
    | forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
key forall a. Eq a => a -> a -> Bool
== Int
32 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall ba. ba -> ByteSize -> KeyPackage ba
KeyPackage ba
key ByteSize
Bytes32
    | Bool
otherwise = 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 forall ba. ByteArray ba => ba -> Maybe (KeyPackage ba)
buildPackage key
key of Maybe (KeyPackage key)
Nothing -> forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_KeySizeInvalid
                             Just KeyPackage key
keyPackage -> 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 forall a b. (a -> b) -> a -> b
$ forall ba. ByteArray ba => KeyPackage ba -> [Word32]
genK KeyPackage key
keyPackage
                                        generatedS :: (Array32, Array32, Array32, Array32)
generatedS = forall ba.
KeyPackage ba -> [Word8] -> (Array32, Array32, Array32, Array32)
genSboxes KeyPackage key
keyPackage forall a b. (a -> b) -> a -> b
$ 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
    | forall a. ByteArrayAccess a => a -> Bool
B.null ba
rest = ba
blockOutput
    | Bool
otherwise = ba
blockOutput forall bs. ByteArray bs => bs -> bs -> bs
`B.append` forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
mapBlocks ba -> ba
operation ba
rest
        where (ba
block, ba
rest) = 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 = forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
mapBlocks (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 = forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
store32ls (Word32, Word32, Word32, Word32)
ts
    where (Word32
a, Word32
b, Word32
c, Word32
d) = forall ba. ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
load32ls ba
message
          a' :: Word32
a' = Word32
a forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
0
          b' :: Word32
b' = Word32
b forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
1
          c' :: Word32
c' = Word32
c forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
2
          d' :: Word32
d' = Word32
d forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
3
          (!Word32
a'', !Word32
b'', !Word32
c'', !Word32
d'') = 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'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
4, Word32
d'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
5, Word32
a'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
6, Word32
b'' 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] = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Int
offset -> Array32 -> Int -> Word32
arrayRead32 Array32
ks forall a b. (a -> b) -> a -> b
$ (Int
8 forall a. Num a => a -> a -> a
+ Int
4 forall a. Num a => a -> a -> a
* Int
ind) forall a. Num a => a -> a -> a
+ Int
offset) [Int
0..Int
3]
                  t2 :: Word32
t2 = Array32 -> Word32 -> Word32
byteIndex Array32
s2 Word32
retB forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s1 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB Int
24)
                  t1 :: Word32
t1 = (Array32 -> Word32 -> Word32
byteIndex Array32
s1 Word32
retA forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s2 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA Int
24)) forall a. Num a => a -> a -> a
+ Word32
t2
                  retC' :: Word32
retC' = forall a. Bits a => a -> Int -> a
rotateR (Word32
retC forall a. Bits a => a -> a -> a
`xor` (Word32
t1 forall a. Num a => a -> a -> a
+ Word32
k0)) Int
1
                  retD' :: Word32
retD' = forall a. Bits a => a -> Int -> a
rotateL Word32
retD Int
1 forall a. Bits a => a -> a -> a
`xor` (Word32
t1 forall a. Num a => a -> a -> a
+ Word32
t2 forall a. Num a => a -> a -> a
+ Word32
k1)
                  t2' :: Word32
t2' = Array32 -> Word32 -> Word32
byteIndex Array32
s2 Word32
retD' forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD' Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD' Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s1 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD' Int
24)
                  t1' :: Word32
t1' = (Array32 -> Word32 -> Word32
byteIndex Array32
s1 Word32
retC' forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s2 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC' Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC' Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC' Int
24)) forall a. Num a => a -> a -> a
+ Word32
t2'
                  retA' :: Word32
retA' = forall a. Bits a => a -> Int -> a
rotateR (Word32
retA forall a. Bits a => a -> a -> a
`xor` (Word32
t1' forall a. Num a => a -> a -> a
+ Word32
k2)) Int
1
                  retB' :: Word32
retB' = forall a. Bits a => a -> Int -> a
rotateL Word32
retB Int
1 forall a. Bits a => a -> a -> a
`xor` (Word32
t1' forall a. Num a => a -> a -> a
+ Word32
t2' 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 forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
byte
    where byte :: Word32
byte = Word32
ind 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 = forall ba. ByteArray ba => (ba -> ba) -> ba -> ba
mapBlocks (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 = forall ba. ByteArray ba => (Word32, Word32, Word32, Word32) -> ba
store32ls (Word32, Word32, Word32, Word32)
ixs
    where (Word32
a, Word32
b, Word32
c, Word32
d) = forall ba. ByteArray ba => ba -> (Word32, Word32, Word32, Word32)
load32ls ba
message
          a' :: Word32
a' = Word32
c forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
6
          b' :: Word32
b' = Word32
d forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
7
          c' :: Word32
c' = Word32
a forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
4
          d' :: Word32
d' = Word32
b forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
5
          (!Word32
a'', !Word32
b'', !Word32
c'', !Word32
d'') = 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'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
0, Word32
b'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
1, Word32
c'' forall a. Bits a => a -> a -> a
`xor` Array32 -> Int -> Word32
arrayRead32 Array32
ks Int
2, Word32
d'' 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] = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Int
offset -> Array32 -> Int -> Word32
arrayRead32 Array32
ks forall a b. (a -> b) -> a -> b
$ (Int
4 forall a. Num a => a -> a -> a
+ Int
4 forall a. Num a => a -> a -> a
* Int
ind) forall a. Num a => a -> a -> a
+ Int
offset) [Int
0..Int
3]
                  t2 :: Word32
t2 = Array32 -> Word32 -> Word32
byteIndex Array32
s2 Word32
retD forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s1 (forall a. Bits a => a -> Int -> a
shiftR Word32
retD Int
24)
                  t1 :: Word32
t1 = (Array32 -> Word32 -> Word32
byteIndex Array32
s1 Word32
retC forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s2 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retC Int
24)) forall a. Num a => a -> a -> a
+ Word32
t2
                  retA' :: Word32
retA' = forall a. Bits a => a -> Int -> a
rotateL Word32
retA Int
1 forall a. Bits a => a -> a -> a
`xor` (Word32
t1 forall a. Num a => a -> a -> a
+ Word32
k2)
                  retB' :: Word32
retB' = forall a. Bits a => a -> Int -> a
rotateR (Word32
retB forall a. Bits a => a -> a -> a
`xor` (Word32
t2 forall a. Num a => a -> a -> a
+ Word32
t1 forall a. Num a => a -> a -> a
+ Word32
k3)) Int
1
                  t2' :: Word32
t2' = Array32 -> Word32 -> Word32
byteIndex Array32
s2 Word32
retB' forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB' Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB' Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s1 (forall a. Bits a => a -> Int -> a
shiftR Word32
retB' Int
24)
                  t1' :: Word32
t1' = (Array32 -> Word32 -> Word32
byteIndex Array32
s1 Word32
retA' forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s2 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA' Int
8) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s3 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA' Int
16) forall a. Bits a => a -> a -> a
`xor` Array32 -> Word32 -> Word32
byteIndex Array32
s4 (forall a. Bits a => a -> Int -> a
shiftR Word32
retA' Int
24)) forall a. Num a => a -> a -> a
+ Word32
t2'
                  retC' :: Word32
retC' = forall a. Bits a => a -> Int -> a
rotateL Word32
retC Int
1 forall a. Bits a => a -> a -> a
`xor` (Word32
t1' forall a. Num a => a -> a -> a
+ Word32
k0)
                  retD' :: Word32
retD' = forall a. Bits a => a -> Int -> a
rotateR (Word32
retD forall a. Bits a => a -> a -> a
`xor` (Word32
t2' forall a. Num a => a -> a -> a
+ Word32
t1' 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 = (forall ba. ByteArray ba => ba -> Word32
intify ba
q1, forall ba. ByteArray ba => ba -> Word32
intify ba
q2, forall ba. ByteArray ba => ba -> Word32
intify ba
q3, forall ba. ByteArray ba => ba -> Word32
intify ba
q4)
    where (ba
half1, ba
half2) = forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
8 ba
message
          (ba
q1, ba
q2) = forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
4 ba
half1
          (ba
q3, ba
q4) = 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 = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Word32
int (!Word8
word, !Int
ind) -> Word32
int forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
shiftL (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
word) (Int
ind forall a. Num a => a -> a -> a
* Int
8) ) Word32
0 (forall a b. [a] -> [b] -> [(a, b)]
zip (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) = forall a. ByteArray a => [Word8] -> a
B.pack forall a b. (a -> b) -> a -> b
$ 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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Int
ind -> forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
shiftR Word32
w (Int
8 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 = forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
key forall a. Integral a => a -> a -> a
`div` Int
2
          sWord :: [Word8]
sWord = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Int
wordIndex ->
                        forall a b. (a -> b) -> [a] -> [b]
map (\[Word8]
rsRow ->
                            forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Word8
acc (!Word8
rsVal, !Int
colIndex) ->
                                Word8
acc forall a. Bits a => a -> a -> a
`xor` Word32 -> Word8 -> Word8 -> Word8
gfMult Word32
rsPolynomial (forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key forall a b. (a -> b) -> a -> b
$ Int
8 forall a. Num a => a -> a -> a
* Int
wordIndex forall a. Num a => a -> a -> a
+ Int
colIndex) Word8
rsVal
                                ) Word8
0 (forall a b. [a] -> [b] -> [(a, b)]
zip [Word8]
rsRow [Int
0..])
                            ) [[Word8]]
rs
                    ) [Int
0..Int
word64Count forall a. Num a => a -> a -> a
- Int
1]

data Column = Zero | One | Two | Three deriving (Int -> Column -> ShowS
[Column] -> ShowS
Column -> String
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
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]
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
forall a. a -> a -> Bounded a
maxBound :: Column
$cmaxBound :: Column
minBound :: Column
$cminBound :: 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] = forall a. Int -> [a] -> [a]
take Int
16 [Word8]
ws
          ([Word32]
b0', [Word32]
b1', [Word32]
b2', [Word32]
b3') = ByteSize -> ([Word32], [Word32], [Word32], [Word32])
sboxBySize forall a b. (a -> b) -> a -> b
$ 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 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w0) forall a. Bits a => a -> a -> a
`xor` Word8
w4)) Column
Zero
                  !b1 :: [Word32]
b1 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w1) forall a. Bits a => a -> a -> a
`xor` Word8
w5)) Column
One
                  !b2 :: [Word32]
b2 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w2) forall a. Bits a => a -> a -> a
`xor` Word8
w6)) Column
Two
                  !b3 :: [Word32]
b3 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w3) 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 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w0) forall a. Bits a => a -> a -> a
`xor` Word8
w4) forall a. Bits a => a -> a -> a
`xor` Word8
w8)) Column
Zero
                  !b1 :: [Word32]
b1 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w1) forall a. Bits a => a -> a -> a
`xor` Word8
w5) forall a. Bits a => a -> a -> a
`xor` Word8
w9)) Column
One
                  !b2 :: [Word32]
b2 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w2) forall a. Bits a => a -> a -> a
`xor` Word8
w6) forall a. Bits a => a -> a -> a
`xor` Word8
w10)) Column
Two
                  !b3 :: [Word32]
b3 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w3) forall a. Bits a => a -> a -> a
`xor` Word8
w7) 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 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w0) forall a. Bits a => a -> a -> a
`xor` Word8
w4) forall a. Bits a => a -> a -> a
`xor` Word8
w8) forall a. Bits a => a -> a -> a
`xor` Word8
w12)) Column
Zero
                  !b1 :: [Word32]
b1 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w1) forall a. Bits a => a -> a -> a
`xor` Word8
w5) forall a. Bits a => a -> a -> a
`xor` Word8
w9) forall a. Bits a => a -> a -> a
`xor` Word8
w13)) Column
One
                  !b2 :: [Word32]
b2 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox0 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w2) forall a. Bits a => a -> a -> a
`xor` Word8
w6) forall a. Bits a => a -> a -> a
`xor` Word8
w10) forall a. Bits a => a -> a -> a
`xor` Word8
w14)) Column
Two
                  !b3 :: [Word32]
b3 = 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Int -> Word8
sbox1 Int
byte forall a. Bits a => a -> a -> a
`xor` Word8
w3) forall a. Bits a => a -> a -> a
`xor` Word8
w7) forall a. Bits a => a -> a -> a
`xor` Word8
w11) 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 = 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 forall a. Num a => a -> a -> a
+ Word32
b', forall a. Bits a => a -> Int -> a
rotateL (Word32
2 forall a. Num a => a -> a -> a
* Word32
b' forall a. Num a => a -> a -> a
+ Word32
a) Int
9]
            where tmp1 :: [Word8]
tmp1 = forall a. Int -> a -> [a]
replicate Int
4 forall a b. (a -> b) -> a -> b
$ Word8
2 forall a. Num a => a -> a -> a
* Word8
idx
                  tmp2 :: [Word8]
tmp2 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Num a => a -> a -> a
+Word8
1) [Word8]
tmp1
                  a :: Word32
a = forall ba.
ByteArray ba =>
[Word8] -> KeyPackage ba -> Int -> Word32
h [Word8]
tmp1 KeyPackage ba
keyPackage Int
0
                  b :: Word32
b = forall ba.
ByteArray ba =>
[Word8] -> KeyPackage ba -> Int -> Word32
h [Word8]
tmp2 KeyPackage ba
keyPackage Int
1
                  b' :: Word32
b' = 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 =  forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Word32 -> (Word8, Column) -> Word32
xorMdsColMult Word32
0 forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip [Word8
y0f, Word8
y1f, Word8
y2f, Word8
y3f] forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> [a]
enumFrom Column
Zero
    where key :: ba
key = forall ba. KeyPackage ba -> ba
rawKeyBytes KeyPackage ba
keyPackage
          [Word8
y0, Word8
y1, Word8
y2, Word8
y3] = 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) forall a b. (a -> b) -> a -> b
$ 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 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y0'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
6 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
0)
                  y1' :: Word8
y1' = Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y1'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
6 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
1)
                  y2' :: Word8
y2' = Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y2'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
6 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
2)
                  y3' :: Word8
y3' = Int -> Word8
sbox1 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y3'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
6 forall a. Num a => a -> a -> a
+ Int
offset) 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 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y0'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
4 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
0)
                  y1' :: Word8
y1' = Int -> Word8
sbox1 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y1'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
4 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
1)
                  y2' :: Word8
y2' = Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y2'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
4 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
2)
                  y3' :: Word8
y3' = Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y3'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
4 forall a. Num a => a -> a -> a
+ Int
offset) 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y0'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
2 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
0))) forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
0 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
0)
                  y1' :: Word8
y1' = Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox1 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y1'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
2 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
1))) forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
0 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
1)
                  y2' :: Word8
y2' = Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox0 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y2'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
2 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
2))) forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
0 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
2)
                  y3' :: Word8
y3' = Int -> Word8
sbox0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Int -> Word8
sbox1 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y3'') forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
2 forall a. Num a => a -> a -> a
+ Int
offset) forall a. Num a => a -> a -> a
+ Int
3))) forall a. Bits a => a -> a -> a
`xor` forall a. ByteArrayAccess a => a -> Int -> Word8
B.index ba
key (Int
4 forall a. Num a => a -> a -> a
* (Int
0 forall a. Num a => a -> a -> a
+ Int
offset) 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 forall a. Bits a => a -> a -> a
`xor` 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 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mul5B Int
8 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
16 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
24
                Column
One   -> Word32
mulEF forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
8 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mul5B Int
16 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
input Int
24
                Column
Two   -> Word32
mul5B forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
8 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
input Int
16 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
24
                Column
Three -> Word32
mul5B forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
input Int
8 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mulEF Int
16 forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
rotateL Word32
mul5B Int
24
        where input :: Word32
input = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
byte
              mul5B :: Word32
mul5B = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word32 -> Word8 -> Word8 -> Word8
gfMult Word32
mdsPolynomial Word8
byte Word8
0x5B
              mulEF :: Word32
mulEF = forall a b. (Integral a, Num b) => a -> b
fromIntegral 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
    | forall a. Bits a => a -> Int -> Bool
testBit b
b Int
0 = forall a b. (a, b) -> b
snd
    | Bool
otherwise = forall a b. (a, b) -> a
fst

gfMult :: Word32 -> Word8 -> Word8 -> Word8
gfMult :: Word32 -> Word8 -> Word8 -> Word8
gfMult Word32
p Word8
a Word8
b = forall a b. (Integral a, Num b) => a -> b
fromIntegral 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, 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 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 forall a. Num a => a -> a -> a
+ Int
1)
                where result'' :: Word32
result'' = Word32
result' forall a. Bits a => a -> a -> a
`xor` forall b a. Bits b => b -> (a, a) -> a
tupInd (Word8
a' forall a. Bits a => a -> a -> a
.&. Word8
1) (Word32, Word32)
b''
                      a'' :: Word8
a'' = forall a. Bits a => a -> Int -> a
shiftR Word8
a' Int
1
                      b''' :: (Word32, Word32)
b''' = (forall a b. (a, b) -> a
fst (Word32, Word32)
b'', forall b a. Bits b => b -> (a, a) -> a
tupInd (forall a. Bits a => a -> Int -> a
shiftR (forall a b. (a, b) -> b
snd (Word32, Word32)
b'') Int
7) (Word32, Word32)
p'' forall a. Bits a => a -> a -> a
`xor` forall a. Bits a => a -> Int -> a
shiftL (forall a b. (a, b) -> b
snd (Word32, Word32)
b'') Int
1)