-----------------------------------------------------------------------------
-- |
-- Module    : Cryptol.AES
-- Copyright : (c) Levent Erkok
-- License   : BSD3
-- Maintainer: erkokl@gmail.com
-- Stability : experimental
--
-- A TBox-based implementation of AES primitives, based on
-- the AES example code from SBV.  Here we've stripped out
-- everything except the basic primitives needed, which
-- essentially boil down to table table lookups in most cases.
-----------------------------------------------------------------------------
{-# LANGUAGE ParallelListComp #-}
module Cryptol.AES
  ( State
  , Key
  , keyExpansionWords
  , invMixColumns
  , aesRound
  , aesFinalRound
  , aesInvRound
  , aesInvFinalRound
  ) where

import Data.Bits
import Data.List (transpose, genericDrop, genericTake)
import Data.Word (Word8, Word32)

-- | An element of the Galois Field 2^8, which are essentially polynomials with
-- maximum degree 7. They are conveniently represented as values between 0 and 255.
type GF28 = Word8

-----------------------------------------------------------------------------
-- ** Types and basic operations
-----------------------------------------------------------------------------
-- | AES state. The state consists of four 32-bit words, each of which is in turn treated
-- as four GF28's, i.e., 4 bytes. The T-Box implementation keeps the four-bytes together
-- for efficient representation.
type State = [Word32]

-- | The key, which can be 128, 192, or 256 bits. Represented as a sequence of 32-bit words.
type Key = [Word32]

-- | Rotating a state row by a fixed amount to the right.
rotR :: [GF28] -> Int -> [GF28]
rotR :: [GF28] -> Int -> [GF28]
rotR [GF28
a, GF28
b, GF28
c, GF28
d] Int
1 = [GF28
d, GF28
a, GF28
b, GF28
c]
rotR [GF28
a, GF28
b, GF28
c, GF28
d] Int
2 = [GF28
c, GF28
d, GF28
a, GF28
b]
rotR [GF28
a, GF28
b, GF28
c, GF28
d] Int
3 = [GF28
b, GF28
c, GF28
d, GF28
a]
rotR [GF28]
xs           Int
i = [Char] -> [GF28]
forall a. HasCallStack => [Char] -> a
error ([Char] -> [GF28]) -> [Char] -> [GF28]
forall a b. (a -> b) -> a -> b
$ [Char]
"rotR: Unexpected input: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ ([GF28], Int) -> [Char]
forall a. Show a => a -> [Char]
show ([GF28]
xs, Int
i)


toBytes :: Word32 -> [Word8]
toBytes :: Word32 -> [GF28]
toBytes Word32
w = [GF28
b0,GF28
b1,GF28
b2,GF28
b3]
  where
  b0 :: GF28
b0 = Word32 -> GF28
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
24)
  b1 :: GF28
b1 = Word32 -> GF28
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
16)
  b2 :: GF28
b2 = Word32 -> GF28
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR`  Int
8)
  b3 :: GF28
b3 = Word32 -> GF28
forall a b. (Integral a, Num b) => a -> b
fromIntegral  Word32
w

fromBytes :: [Word8] -> Word32
fromBytes :: [GF28] -> Word32
fromBytes [GF28
b0,GF28
b1,GF28
b2,GF28
b3] = Word32
w
  where
  w :: Word32
w = ((GF28 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
b0) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
24) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
      ((GF28 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
b1) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
16) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
      ((GF28 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
b2) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL`  Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
       (GF28 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
b3)
fromBytes [GF28]
bs = [Char] -> Word32
forall a. HasCallStack => [Char] -> a
error ([Char]
"Unexpected list length in fromBytes: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show ([GF28] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [GF28]
bs))


-----------------------------------------------------------------------------
-- ** GF28 multiplication tables
-----------------------------------------------------------------------------

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

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


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

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


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

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


-- table-lookup versions of gf28Mult with the constants used in invMixColumns
-- and TBox construction

m2 :: GF28 -> GF28
m2 :: GF28 -> GF28
m2 GF28
i = [GF28]
m2Table [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

m3 :: GF28 -> GF28
m3 :: GF28 -> GF28
m3 GF28
i = [GF28]
m3Table [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

mE :: GF28 -> GF28
mE :: GF28 -> GF28
mE GF28
i = [GF28]
mETable [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

mB :: GF28 -> GF28
mB :: GF28 -> GF28
mB GF28
i = [GF28]
mBTable [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

mD :: GF28 -> GF28
mD :: GF28 -> GF28
mD GF28
i = [GF28]
mDTable [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

m9 :: GF28 -> GF28
m9 :: GF28 -> GF28
m9 GF28
i = [GF28]
m9Table [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

-----------------------------------------------------------------------------
-- ** The key schedule
-----------------------------------------------------------------------------

-- | The @InvMixColumns@ transformation, as described in Section 5.3.3 of the standard. Note
-- that this transformation is only used explicitly during key-expansion in the T-Box implementation
-- of AES.
invMixColumns :: State -> State
invMixColumns :: State -> State
invMixColumns State
state = ([GF28] -> Word32) -> [[GF28]] -> State
forall a b. (a -> b) -> [a] -> [b]
map [GF28] -> Word32
fromBytes ([[GF28]] -> State) -> [[GF28]] -> State
forall a b. (a -> b) -> a -> b
$ [[GF28]] -> [[GF28]]
forall a. [[a]] -> [[a]]
transpose ([[GF28]] -> [[GF28]]) -> [[GF28]] -> [[GF28]]
forall a b. (a -> b) -> a -> b
$ [[GF28]] -> [[GF28]]
mmult ((Word32 -> [GF28]) -> State -> [[GF28]]
forall a b. (a -> b) -> [a] -> [b]
map Word32 -> [GF28]
toBytes State
state)
 where dot :: [a -> c] -> [a] -> c
dot [a -> c]
f   = (c -> c -> c) -> [c] -> c
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 c -> c -> c
forall a. Bits a => a -> a -> a
xor ([c] -> c) -> ([a] -> [c]) -> [a] -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> c) -> a -> c) -> [a -> c] -> [a] -> [c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (a -> c) -> a -> c
forall a b. (a -> b) -> a -> b
($) [a -> c]
f
       mmult :: [[Word8]] -> [[Word8]]
       mmult :: [[GF28]] -> [[GF28]]
mmult [[GF28]]
n = [([GF28] -> GF28) -> [[GF28]] -> [GF28]
forall a b. (a -> b) -> [a] -> [b]
map ([GF28 -> GF28] -> [GF28] -> GF28
forall c a. Bits c => [a -> c] -> [a] -> c
dot [GF28 -> GF28]
r) [[GF28]]
n | [GF28 -> GF28]
r <- [ [GF28 -> GF28
mE, GF28 -> GF28
mB, GF28 -> GF28
mD, GF28 -> GF28
m9]
                                       , [GF28 -> GF28
m9, GF28 -> GF28
mE, GF28 -> GF28
mB, GF28 -> GF28
mD]
                                       , [GF28 -> GF28
mD, GF28 -> GF28
m9, GF28 -> GF28
mE, GF28 -> GF28
mB]
                                       , [GF28 -> GF28
mB, GF28 -> GF28
mD, GF28 -> GF28
m9, GF28 -> GF28
mE]
                                       ]]

keyExpansionWords :: Integer -> Key -> [Word32]
keyExpansionWords :: Integer -> State -> State
keyExpansionWords Integer
nk State
key = Integer -> State -> State
forall i a. Integral i => i -> [a] -> [a]
genericTake (Integer
4Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*(Integer
nkInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
7)) State
keys
   where keys :: [Word32]
         keys :: State
keys = State
key State -> State -> State
forall a. [a] -> [a] -> [a]
++ [Integer -> Word32 -> Word32 -> Word32
nextWord Integer
i Word32
prev Word32
old | Integer
i <- [Integer
nk ..] | Word32
prev <- Integer -> State -> State
forall i a. Integral i => i -> [a] -> [a]
genericDrop (Integer
nkInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1) State
keys | Word32
old <- State
keys]

         nextWord :: Integer -> Word32 -> Word32 -> Word32
         nextWord :: Integer -> Word32 -> Word32 -> Word32
nextWord Integer
i Word32
prev Word32
old
           | Integer
i Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
nk Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0           = Word32
old Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32 -> GF28 -> Word32
subWordRcon (Word32
prev Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`rotateL` Int
8) ([GF28]
roundConstants [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer
i Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
nk))
           | Integer
i Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
nk Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
4 Bool -> Bool -> Bool
&& Integer
nk Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
6 = Word32
old Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32 -> GF28 -> Word32
subWordRcon Word32
prev GF28
0
           | Bool
True                      = Word32
old Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
prev

         subWordRcon :: Word32 -> GF28 -> Word32
         subWordRcon :: Word32 -> GF28 -> Word32
subWordRcon Word32
w GF28
rc = [GF28] -> Word32
fromBytes [GF28
a GF28 -> GF28 -> GF28
forall a. Bits a => a -> a -> a
`xor` GF28
rc, GF28
b, GF28
c, GF28
d]
            where [GF28
a, GF28
b, GF28
c, GF28
d] = (GF28 -> GF28) -> [GF28] -> [GF28]
forall a b. (a -> b) -> [a] -> [b]
map GF28 -> GF28
sbox ([GF28] -> [GF28]) -> [GF28] -> [GF28]
forall a b. (a -> b) -> a -> b
$ Word32 -> [GF28]
toBytes Word32
w


-- | Definition of round-constants, as specified in Section 5.2 of the AES standard.
--   We only need up to the 11th value for AES-128, and fewer than that for AES-192
--   and AES-256.
roundConstants :: [GF28]
roundConstants :: [GF28]
roundConstants = [GF28
0,GF28
1,GF28
2,GF28
4,GF28
8,GF28
16,GF28
32,GF28
64,GF28
128,GF28
27,GF28
54]

-----------------------------------------------------------------------------
-- ** The S-box transformation
-----------------------------------------------------------------------------

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

-- | The AES sbox transformation
sbox :: GF28 -> GF28
sbox :: GF28 -> GF28
sbox GF28
i = [GF28]
sboxTable [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

-----------------------------------------------------------------------------
-- ** The inverse S-box transformation
-----------------------------------------------------------------------------

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

-- | The inverse s-box transformation.
unSBox :: GF28 -> GF28
unSBox :: GF28 -> GF28
unSBox GF28
i = [GF28]
unSBoxTable [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i


-----------------------------------------------------------------------------
-- ** Tables for T-Box encryption
-----------------------------------------------------------------------------

-- | T-box table generation function for encryption
t0Func :: GF28 -> [GF28]
t0Func :: GF28 -> [GF28]
t0Func GF28
a = [ GF28 -> GF28
m2 GF28
s, GF28
s, GF28
s, GF28 -> GF28
m3 GF28
s]
  where s :: GF28
s = GF28 -> GF28
sbox GF28
a

-- | First look-up table used in encryption
t0 :: GF28 -> Word32
t0 :: GF28 -> Word32
t0 GF28
i = State
t0Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

t0Table :: [Word32]
t0Table :: State
t0Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
t0Func GF28
a)          | GF28
a <- [GF28
0..GF28
255]]

-- | Second look-up table used in encryption
t1 :: GF28 -> Word32
t1 :: GF28 -> Word32
t1 GF28
i = State
t1Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

t1Table :: [Word32]
t1Table :: State
t1Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
t0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
1) | GF28
a <- [GF28
0..GF28
255]]

-- | Third look-up table used in encryption
t2 :: GF28 -> Word32
t2 :: GF28 -> Word32
t2 GF28
i = State
t2Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

t2Table :: [Word32]
t2Table :: State
t2Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
t0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
2) | GF28
a <- [GF28
0..GF28
255]]

-- | Fourth look-up table used in encryption
t3 :: GF28 -> Word32
t3 :: GF28 -> Word32
t3 GF28
i = State
t3Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

t3Table :: [Word32]
t3Table :: State
t3Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
t0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
3) | GF28
a <- [GF28
0..GF28
255]]

-----------------------------------------------------------------------------
-- ** Tables for T-Box decryption
-----------------------------------------------------------------------------

-- | T-box table generating function for decryption
u0Func :: GF28 -> [GF28]
u0Func :: GF28 -> [GF28]
u0Func GF28
a = [ GF28 -> GF28
mE GF28
s, GF28 -> GF28
m9 GF28
s, GF28 -> GF28
mD GF28
s, GF28 -> GF28
mB GF28
s ]
 where s :: GF28
s = GF28 -> GF28
unSBox GF28
a

-- | First look-up table used in decryption
u0 :: GF28 -> Word32
u0 :: GF28 -> Word32
u0 GF28
i = State
u0Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

u0Table :: [Word32]
u0Table :: State
u0Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
u0Func GF28
a)          | GF28
a <- [GF28
0..GF28
255]]

-- | Second look-up table used in decryption
u1 :: GF28 -> Word32
u1 :: GF28 -> Word32
u1 GF28
i = State
u1Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

u1Table :: [Word32]
u1Table :: State
u1Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
u0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
1) | GF28
a <- [GF28
0..GF28
255]]

-- | Third look-up table used in decryption
u2 :: GF28 -> Word32
u2 :: GF28 -> Word32
u2 GF28
i = State
u2Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

u2Table :: [Word32]
u2Table :: State
u2Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
u0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
2) | GF28
a <- [GF28
0..GF28
255]]

-- | Fourth look-up table used in decryption
u3 :: GF28 -> Word32
u3 :: GF28 -> Word32
u3 GF28
i = State
u3Table State -> Int -> Word32
forall a. [a] -> Int -> a
!! GF28 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral GF28
i

u3Table :: [Word32]
u3Table :: State
u3Table = [[GF28] -> Word32
fromBytes (GF28 -> [GF28]
u0Func GF28
a [GF28] -> Int -> [GF28]
`rotR` Int
3) | GF28
a <- [GF28
0..GF28
255]]

-----------------------------------------------------------------------------
-- ** AES rounds
-----------------------------------------------------------------------------

aesRound :: State -> State
aesRound :: State -> State
aesRound State
s = State
d
  where d :: State
d = (Int -> Word32) -> [Int] -> State
forall a b. (a -> b) -> [a] -> [b]
map Int -> Word32
f [Int
0..Int
3]
        a :: [[GF28]]
a = (Word32 -> [GF28]) -> State -> [[GF28]]
forall a b. (a -> b) -> [a] -> [b]
map Word32 -> [GF28]
toBytes State
s
        f :: Int -> Word32
f Int
j = Word32
e0 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e1 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e2 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e3
              where e0 :: Word32
e0 = GF28 -> Word32
t0 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
0) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
0)
                    e1 :: Word32
e1 = GF28 -> Word32
t1 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
1)
                    e2 :: Word32
e2 = GF28 -> Word32
t2 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
2)
                    e3 :: Word32
e3 = GF28 -> Word32
t3 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
3)

aesFinalRound :: State -> State
aesFinalRound :: State -> State
aesFinalRound State
s = State
d
  where d :: State
d = (Int -> Word32) -> [Int] -> State
forall a b. (a -> b) -> [a] -> [b]
map Int -> Word32
f [Int
0..Int
3]
        a :: [[GF28]]
a = (Word32 -> [GF28]) -> State -> [[GF28]]
forall a b. (a -> b) -> [a] -> [b]
map Word32 -> [GF28]
toBytes State
s
        f :: Int -> Word32
f Int
j = [GF28] -> Word32
fromBytes [ GF28 -> GF28
sbox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
0) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
0)
                        , GF28 -> GF28
sbox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
1)
                        , GF28 -> GF28
sbox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
2)
                        , GF28 -> GF28
sbox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
3)
                        ]

aesInvRound :: State -> State
aesInvRound :: State -> State
aesInvRound State
s = State
d
  where d :: State
d = (Int -> Word32) -> [Int] -> State
forall a b. (a -> b) -> [a] -> [b]
map Int -> Word32
f [Int
0..Int
3]
        a :: [[GF28]]
a = (Word32 -> [GF28]) -> State -> [[GF28]]
forall a b. (a -> b) -> [a] -> [b]
map Word32 -> [GF28]
toBytes State
s
        f :: Int -> Word32
f Int
j = Word32
e0 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e1 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e2 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
`xor` Word32
e3
              where e0 :: Word32
e0 = GF28 -> Word32
u0 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
0) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
0)
                    e1 :: Word32
e1 = GF28 -> Word32
u1 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
1)
                    e2 :: Word32
e2 = GF28 -> Word32
u2 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
2)
                    e3 :: Word32
e3 = GF28 -> Word32
u3 ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
3)

aesInvFinalRound :: State -> State
aesInvFinalRound :: State -> State
aesInvFinalRound State
s = State
d
  where d :: State
d = (Int -> Word32) -> [Int] -> State
forall a b. (a -> b) -> [a] -> [b]
map Int -> Word32
f [Int
0..Int
3]
        a :: [[GF28]]
a = (Word32 -> [GF28]) -> State -> [[GF28]]
forall a b. (a -> b) -> [a] -> [b]
map Word32 -> [GF28]
toBytes State
s
        f :: Int -> Word32
f Int
j = [GF28] -> Word32
fromBytes [ GF28 -> GF28
unSBox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
0) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
0)
                        , GF28 -> GF28
unSBox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
1)
                        , GF28 -> GF28
unSBox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
2)
                        , GF28 -> GF28
unSBox ([[GF28]]
a [[GF28]] -> Int -> [GF28]
forall a. [a] -> Int -> a
!! ((Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
4) [GF28] -> Int -> GF28
forall a. [a] -> Int -> a
!! Int
3)
                        ]