    -- |
    -- Module      : Crypto.Cipher.Camellia.Primitive
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : Good
    --
    -- this only cover Camellia 128 bits for now, API will change once
    -- 192 and 256 mode are implemented too

    module Crypto.Cipher.Camellia.Primitive
        ( Camellia
        , initCamellia
        , encrypt
        , decrypt
        ) where

    import Data.Word
    import Data.Vector.Unboxed
    import Data.Bits
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Unsafe as B

    data Mode = Decrypt | Encrypt

    -- should probably use crypto large word ?
    data Word128 = Word128 !Word64 !Word64 deriving (Int -> Word128 -> ShowS
    [Word128] -> ShowS
    Word128 -> String
    (Int -> Word128 -> ShowS)
    -> (Word128 -> String) -> ([Word128] -> ShowS) -> Show Word128
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Word128 -> ShowS
    showsPrec :: Int -> Word128 -> ShowS
    $cshow :: Word128 -> String
    show :: Word128 -> String
    $cshowList :: [Word128] -> ShowS
    showList :: [Word128] -> ShowS
    Show, Word128 -> Word128 -> Bool
    (Word128 -> Word128 -> Bool)
    -> (Word128 -> Word128 -> Bool) -> Eq Word128
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Word128 -> Word128 -> Bool
    == :: Word128 -> Word128 -> Bool
    $c/= :: Word128 -> Word128 -> Bool
    /= :: Word128 -> Word128 -> Bool
    Eq)

    w128tow64 :: Word128 -> (Word64, Word64)
    w128tow64 :: Word128 -> (Word64, Word64)
    w128tow64 (Word128 Word64
    w1 Word64
    w2) = (Word64
    w1, Word64
    w2)

    w64tow128 :: (Word64, Word64) -> Word128
    w64tow128 :: (Word64, Word64) -> Word128
    w64tow128 (Word64
    x1, Word64
    x2) = Word64 -> Word64 -> Word128
    Word128 Word64
    x1 Word64
    x2

    w64tow8 :: Word64 -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)
    w64tow8 :: Word64 -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)
    w64tow8 Word64
    x = (Word8
    t1, Word8
    t2, Word8
    t3, Word8
    t4, Word8
    t5, Word8
    t6, Word8
    t7, Word8
    t8)
        where
            t1 :: Word8
    t1 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    56)
            t2 :: Word8
    t2 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    48)
            t3 :: Word8
    t3 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    40)
            t4 :: Word8
    t4 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32)
            t5 :: Word8
    t5 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    24)
            t6 :: Word8
    t6 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    16)
            t7 :: Word8
    t7 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    8)
            t8 :: Word8
    t8 = Word64 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    x)

    w8tow64 :: B.ByteString -> Word64
    w8tow64 :: ByteString -> Word64
    w8tow64 ByteString
    b = (Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t1 Int
    56 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t2 Int
    48 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t3 Int
    40 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t4 Int
    32 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t5 Int
    24 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t6 Int
    16 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t7 Int
    8 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word8 -> Int -> Word64
    forall {a} {a}. (Bits a, Integral a, Num a) => a -> Int -> a
    sh Word8
    t8 Int
    0)
        where
            t1 :: Word8
    t1     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    0
            t2 :: Word8
    t2     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    1
            t3 :: Word8
    t3     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    2
            t4 :: Word8
    t4     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    3
            t5 :: Word8
    t5     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    4
            t6 :: Word8
    t6     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    5
            t7 :: Word8
    t7     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    6
            t8 :: Word8
    t8     = ByteString -> Int -> Word8
    B.unsafeIndex ByteString
    b Int
    7
            sh :: a -> Int -> a
    sh a
    i Int
    r = (a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    i) a -> Int -> a
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    r

    w64tow32 :: Word64 -> (Word32, Word32)
    w64tow32 :: Word64 -> (Word32, Word32)
    w64tow32 Word64
    w = (Word64 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32), Word64 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    w Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffffffff))

    w32tow64 :: (Word32, Word32) -> Word64
    w32tow64 :: (Word32, Word32) -> Word64
    w32tow64 (Word32
    x1, Word32
    x2) = ((Word32 -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    x1) Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. (Word32 -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word32
    x2)

    w128tow8 :: Word128 -> [Word8]
    w128tow8 :: Word128 -> [Word8]
    w128tow8 (Word128 Word64
    x1 Word64
    x2) = [Word8
    t1,Word8
    t2,Word8
    t3,Word8
    t4,Word8
    t5,Word8
    t6,Word8
    t7,Word8
    t8,Word8
    u1,Word8
    u2,Word8
    u3,Word8
    u4,Word8
    u5,Word8
    u6,Word8
    u7,Word8
    u8]
        where
            (Word8
    t1, Word8
    t2, Word8
    t3, Word8
    t4, Word8
    t5, Word8
    t6, Word8
    t7, Word8
    t8) = Word64 -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)
    w64tow8 Word64
    x1
            (Word8
    u1, Word8
    u2, Word8
    u3, Word8
    u4, Word8
    u5, Word8
    u6, Word8
    u7, Word8
    u8) = Word64 -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)
    w64tow8 Word64
    x2

    getWord64 :: B.ByteString -> Word64
    getWord64 :: ByteString -> Word64
    getWord64 ByteString
    s = Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    0 Int
    56 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    1 Int
    48 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    2 Int
    40 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    3 Int
    32 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    4 Int
    24 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    5 Int
    16 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    6 Int
    8 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Int -> Int -> Word64
    forall {a}. (Bits a, Num a) => Int -> Int -> a
    sh Int
    7 Int
    0
        where
            sh :: Int -> Int -> a
    sh Int
    i Int
    l = (Word8 -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (ByteString
    s HasCallStack => ByteString -> Int -> Word8
    ByteString -> Int -> Word8
    `B.index` Int
    i) a -> Int -> a
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    l)

    getWord128 :: B.ByteString -> Word128
    getWord128 :: ByteString -> Word128
    getWord128 ByteString
    s = Word64 -> Word64 -> Word128
    Word128 (ByteString -> Word64
    getWord64 ByteString
    s) (ByteString -> Word64
    getWord64 (Int -> ByteString -> ByteString
    B.drop Int
    8 ByteString
    s))

    putWord128 :: Word128 -> B.ByteString
    putWord128 :: Word128 -> ByteString
    putWord128 = [Word8] -> ByteString
    B.pack ([Word8] -> ByteString)
    -> (Word128 -> [Word8]) -> Word128 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word128 -> [Word8]
    w128tow8

    sbox :: Vector Word8
    sbox :: Vector Word8
    sbox = [Word8] -> Vector Word8
    forall a. Unbox a => [a] -> Vector a
    fromList
        [Word8
    112,Word8
    130, Word8
    44,Word8
    236,Word8
    179, Word8
    39,Word8
    192,Word8
    229,Word8
    228,Word8
    133, Word8
    87, Word8
    53,Word8
    234, Word8
    12,Word8
    174, Word8
    65
        , Word8
    35,Word8
    239,Word8
    107,Word8
    147, Word8
    69, Word8
    25,Word8
    165, Word8
    33,Word8
    237, Word8
    14, Word8
    79, Word8
    78, Word8
    29,Word8
    101,Word8
    146,Word8
    189
        ,Word8
    134,Word8
    184,Word8
    175,Word8
    143,Word8
    124,Word8
    235, Word8
    31,Word8
    206, Word8
    62, Word8
    48,Word8
    220, Word8
    95, Word8
    94,Word8
    197, Word8
    11, Word8
    26
        ,Word8
    166,Word8
    225, Word8
    57,Word8
    202,Word8
    213, Word8
    71, Word8
    93, Word8
    61,Word8
    217,  Word8
    1, Word8
    90,Word8
    214, Word8
    81, Word8
    86,Word8
    108, Word8
    77
        ,Word8
    139, Word8
    13,Word8
    154,Word8
    102,Word8
    251,Word8
    204,Word8
    176, Word8
    45,Word8
    116, Word8
    18, Word8
    43, Word8
    32,Word8
    240,Word8
    177,Word8
    132,Word8
    153
        ,Word8
    223, Word8
    76,Word8
    203,Word8
    194, Word8
    52,Word8
    126,Word8
    118,  Word8
    5,Word8
    109,Word8
    183,Word8
    169, Word8
    49,Word8
    209, Word8
    23,  Word8
    4,Word8
    215
        , Word8
    20, Word8
    88, Word8
    58, Word8
    97,Word8
    222, Word8
    27, Word8
    17, Word8
    28, Word8
    50, Word8
    15,Word8
    156, Word8
    22, Word8
    83, Word8
    24,Word8
    242, Word8
    34
        ,Word8
    254, Word8
    68,Word8
    207,Word8
    178,Word8
    195,Word8
    181,Word8
    122,Word8
    145, Word8
    36,  Word8
    8,Word8
    232,Word8
    168, Word8
    96,Word8
    252,Word8
    105, Word8
    80
        ,Word8
    170,Word8
    208,Word8
    160,Word8
    125,Word8
    161,Word8
    137, Word8
    98,Word8
    151, Word8
    84, Word8
    91, Word8
    30,Word8
    149,Word8
    224,Word8
    255,Word8
    100,Word8
    210
        , Word8
    16,Word8
    196,  Word8
    0, Word8
    72,Word8
    163,Word8
    247,Word8
    117,Word8
    219,Word8
    138,  Word8
    3,Word8
    230,Word8
    218,  Word8
    9, Word8
    63,Word8
    221,Word8
    148
        ,Word8
    135, Word8
    92,Word8
    131,  Word8
    2,Word8
    205, Word8
    74,Word8
    144, Word8
    51,Word8
    115,Word8
    103,Word8
    246,Word8
    243,Word8
    157,Word8
    127,Word8
    191,Word8
    226
        , Word8
    82,Word8
    155,Word8
    216, Word8
    38,Word8
    200, Word8
    55,Word8
    198, Word8
    59,Word8
    129,Word8
    150,Word8
    111, Word8
    75, Word8
    19,Word8
    190, Word8
    99, Word8
    46
        ,Word8
    233,Word8
    121,Word8
    167,Word8
    140,Word8
    159,Word8
    110,Word8
    188,Word8
    142, Word8
    41,Word8
    245,Word8
    249,Word8
    182, Word8
    47,Word8
    253,Word8
    180, Word8
    89
        ,Word8
    120,Word8
    152,  Word8
    6,Word8
    106,Word8
    231, Word8
    70,Word8
    113,Word8
    186,Word8
    212, Word8
    37,Word8
    171, Word8
    66,Word8
    136,Word8
    162,Word8
    141,Word8
    250
        ,Word8
    114,  Word8
    7,Word8
    185, Word8
    85,Word8
    248,Word8
    238,Word8
    172, Word8
    10, Word8
    54, Word8
    73, Word8
    42,Word8
    104, Word8
    60, Word8
    56,Word8
    241,Word8
    164
        , Word8
    64, Word8
    40,Word8
    211,Word8
    123,Word8
    187,Word8
    201, Word8
    67,Word8
    193, Word8
    21,Word8
    227,Word8
    173,Word8
    244,Word8
    119,Word8
    199,Word8
    128,Word8
    158
        ]

    sbox1 :: Word8 -> Word8
    sbox1 :: Word8 -> Word8
    sbox1 Word8
    x = Vector Word8
    sbox Vector Word8 -> Int -> Word8
    forall a. Unbox a => Vector a -> Int -> a
    ! (Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    x)

    sbox2 :: Word8 -> Word8
    sbox2 :: Word8 -> Word8
    sbox2 Word8
    x = Word8 -> Word8
    sbox1 Word8
    x Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    1;

    sbox3 :: Word8 -> Word8
    sbox3 :: Word8 -> Word8
    sbox3 Word8
    x = Word8 -> Word8
    sbox1 Word8
    x Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    7;

    sbox4 :: Word8 -> Word8
    sbox4 :: Word8 -> Word8
    sbox4 Word8
    x = Word8 -> Word8
    sbox1 (Word8
    x Word8 -> Int -> Word8
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    1);

    sigma1, sigma2, sigma3, sigma4, sigma5, sigma6 :: Word64
    sigma1 :: Word64
    sigma1 = Word64
    0xA09E667F3BCC908B
    sigma2 :: Word64
    sigma2 = Word64
    0xB67AE8584CAA73B2
    sigma3 :: Word64
    sigma3 = Word64
    0xC6EF372FE94F82BE
    sigma4 :: Word64
    sigma4 = Word64
    0x54FF53A5F1D36F1C
    sigma5 :: Word64
    sigma5 = Word64
    0x10E527FADE682D1D
    sigma6 :: Word64
    sigma6 = Word64
    0xB05688C2B3E6C1FD

    rotl128 :: Word128 -> Int -> Word128
    rotl128 :: Word128 -> Int -> Word128
    rotl128 Word128
    v               Int
    0  = Word128
    v
    rotl128 (Word128 Word64
    x1 Word64
    x2) Int
    64 = Word64 -> Word64 -> Word128
    Word128 Word64
    x2 Word64
    x1

    rotl128 v :: Word128
    v@(Word128 Word64
    x1 Word64
    x2) Int
    w
        | Int
    w Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    64    = (Word128
    v Word128 -> Int -> Word128
    `rotl128` Int
    64) Word128 -> Int -> Word128
    `rotl128` (Int
    w Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    64)
        | Bool
    otherwise = Word64 -> Word64 -> Word128
    Word128 (Word64
    x1high Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word64
    x2low) (Word64
    x2high Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word64
    x1low)
            where
                splitBits :: b -> (b, b)
    splitBits b
    i = (b
    i b -> b -> b
    forall a. Bits a => a -> a -> a
    .&. b -> b
    forall a. Bits a => a -> a
    complement b
    x, b
    i b -> b -> b
    forall a. Bits a => a -> a -> a
    .&. b
    x)
                    where x :: b
    x = b
    2 b -> Int -> b
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Int
    w b -> b -> b
    forall a. Num a => a -> a -> a
    - b
    1
                (Word64
    x1high, Word64
    x1low) = Word64 -> (Word64, Word64)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    splitBits (Word64
    x1 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    w)
                (Word64
    x2high, Word64
    x2low) = Word64 -> (Word64, Word64)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    splitBits (Word64
    x2 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    w)

    data Camellia = Camellia
        { Camellia -> Vector Word64
    k  :: Vector Word64
        , Camellia -> Vector Word64
    kw :: Vector Word64
        , Camellia -> Vector Word64
    ke :: Vector Word64
        }

    setKeyInterim :: B.ByteString -> (Word128, Word128, Word128, Word128)
    setKeyInterim :: ByteString -> (Word128, Word128, Word128, Word128)
    setKeyInterim ByteString
    keyseed = ((Word64, Word64) -> Word128
    w64tow128 (Word64, Word64)
    kL, (Word64, Word64) -> Word128
    w64tow128 (Word64, Word64)
    kR, (Word64, Word64) -> Word128
    w64tow128 (Word64, Word64)
    kA, (Word64, Word64) -> Word128
    w64tow128 (Word64, Word64)
    kB)
      where kL :: (Word64, Word64)
    kL = (ByteString -> Word64
    w8tow64 (ByteString -> Word64) -> ByteString -> Word64
    forall a b. (a -> b) -> a -> b
    $ Int -> ByteString -> ByteString
    B.take Int
    8 ByteString
    keyseed, ByteString -> Word64
    w8tow64 (ByteString -> Word64) -> ByteString -> Word64
    forall a b. (a -> b) -> a -> b
    $ Int -> ByteString -> ByteString
    B.drop Int
    8 ByteString
    keyseed)
            kR :: (Word64, Word64)
    kR = (Word64
    0, Word64
    0)

            kA :: (Word64, Word64)
    kA = let d1 :: Word64
    d1 = ((Word64, Word64) -> Word64
    forall a b. (a, b) -> a
    fst (Word64, Word64)
    kL Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Word64, Word64) -> Word64
    forall a b. (a, b) -> a
    fst (Word64, Word64)
    kR)
                     d2 :: Word64
    d2 = ((Word64, Word64) -> Word64
    forall a b. (a, b) -> b
    snd (Word64, Word64)
    kL Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Word64, Word64) -> Word64
    forall a b. (a, b) -> b
    snd (Word64, Word64)
    kR)
                     d3 :: Word64
    d3 = Word64
    d2 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d1 Word64
    sigma1
                     d4 :: Word64
    d4 = Word64
    d1 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d3 Word64
    sigma2
                     d5 :: Word64
    d5 = Word64
    d4 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` ((Word64, Word64) -> Word64
    forall a b. (a, b) -> a
    fst (Word64, Word64)
    kL)
                     d6 :: Word64
    d6 = Word64
    d3 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` ((Word64, Word64) -> Word64
    forall a b. (a, b) -> b
    snd (Word64, Word64)
    kL)
                     d7 :: Word64
    d7 = Word64
    d6 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d5 Word64
    sigma3
                     d8 :: Word64
    d8 = Word64
    d5 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d7 Word64
    sigma4
                  in (Word64
    d8, Word64
    d7)

            kB :: (Word64, Word64)
    kB = let d1 :: Word64
    d1 = ((Word64, Word64) -> Word64
    forall a b. (a, b) -> a
    fst (Word64, Word64)
    kA Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Word64, Word64) -> Word64
    forall a b. (a, b) -> a
    fst (Word64, Word64)
    kR)
                     d2 :: Word64
    d2 = ((Word64, Word64) -> Word64
    forall a b. (a, b) -> b
    snd (Word64, Word64)
    kA Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Word64, Word64) -> Word64
    forall a b. (a, b) -> b
    snd (Word64, Word64)
    kR)
                     d3 :: Word64
    d3 = Word64
    d2 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d1 Word64
    sigma5
                     d4 :: Word64
    d4 = Word64
    d1 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d3 Word64
    sigma6
                  in (Word64
    d4, Word64
    d3)

    -- | Initialize a 128-bit key
    -- Return the initialized key or a error message if the given
    -- keyseed was not 16-bytes in length.
    --
    initCamellia :: B.ByteString -- ^ The seed to use when creating the key
                 -> Either String Camellia
    initCamellia :: ByteString -> Either String Camellia
    initCamellia ByteString
    keyseed
        | ByteString -> Int
    B.length ByteString
    keyseed Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    16 = String -> Either String Camellia
    forall a b. a -> Either a b
    Left String
    "wrong key size"
        | Bool
    otherwise              =
            let (Word128
    kL, Word128
    _, Word128
    kA, Word128
    _) = ByteString -> (Word128, Word128, Word128, Word128)
    setKeyInterim ByteString
    keyseed in

            let (Word64
    kw1, Word64
    kw2) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    0) in
            let (Word64
    k1, Word64
    k2)   = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    0) in
            let (Word64
    k3, Word64
    k4)   = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    15) in
            let (Word64
    k5, Word64
    k6)   = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    15) in
            let (Word64
    ke1, Word64
    ke2) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    30) in --ke1 = (KA <<<  30) >> 64; ke2 = (KA <<<  30) & MASK64;
            let (Word64
    k7, Word64
    k8)   = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    45) in --k7  = (KL <<<  45) >> 64; k8  = (KL <<<  45) & MASK64;
            let (Word64
    k9, Word64
    _)    = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    45) in --k9  = (KA <<<  45) >> 64;
            let (Word64
    _, Word64
    k10)   = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    60) in
            let (Word64
    k11, Word64
    k12) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    60) in
            let (Word64
    ke3, Word64
    ke4) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    77) in
            let (Word64
    k13, Word64
    k14) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    94) in
            let (Word64
    k15, Word64
    k16) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    94) in
            let (Word64
    k17, Word64
    k18) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kL Word128 -> Int -> Word128
    `rotl128` Int
    111) in
            let (Word64
    kw3, Word64
    kw4) = Word128 -> (Word64, Word64)
    w128tow64 (Word128
    kA Word128 -> Int -> Word128
    `rotl128` Int
    111) in

            Camellia -> Either String Camellia
    forall a b. b -> Either a b
    Right (Camellia -> Either String Camellia)
    -> Camellia -> Either String Camellia
    forall a b. (a -> b) -> a -> b
    $ Camellia
                { kw :: Vector Word64
    kw = [Word64] -> Vector Word64
    forall a. Unbox a => [a] -> Vector a
    fromList [ Word64
    kw1, Word64
    kw2, Word64
    kw3, Word64
    kw4 ]
                , ke :: Vector Word64
    ke = [Word64] -> Vector Word64
    forall a. Unbox a => [a] -> Vector a
    fromList [ Word64
    ke1, Word64
    ke2, Word64
    ke3, Word64
    ke4 ]
                , k :: Vector Word64
    k  = [Word64] -> Vector Word64
    forall a. Unbox a => [a] -> Vector a
    fromList [ Word64
    k1, Word64
    k2, Word64
    k3, Word64
    k4, Word64
    k5, Word64
    k6, Word64
    k7, Word64
    k8, Word64
    k9,
                          Word64
    k10, Word64
    k11, Word64
    k12, Word64
    k13, Word64
    k14, Word64
    k15, Word64
    k16, Word64
    k17, Word64
    k18 ]
                }

    feistel :: Word64 -> Word64 -> Word64
    feistel :: Word64 -> Word64 -> Word64
    feistel Word64
    fin Word64
    sk =
        let x :: Word64
    x = Word64
    fin Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64
    sk in
        let (Word8
    t1, Word8
    t2, Word8
    t3, Word8
    t4, Word8
    t5, Word8
    t6, Word8
    t7, Word8
    t8) = Word64 -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8)
    w64tow8 Word64
    x in
        let t1' :: Word8
    t1' = Word8 -> Word8
    sbox1 Word8
    t1 in
        let t2' :: Word8
    t2' = Word8 -> Word8
    sbox2 Word8
    t2 in
        let t3' :: Word8
    t3' = Word8 -> Word8
    sbox3 Word8
    t3 in
        let t4' :: Word8
    t4' = Word8 -> Word8
    sbox4 Word8
    t4 in
        let t5' :: Word8
    t5' = Word8 -> Word8
    sbox2 Word8
    t5 in
        let t6' :: Word8
    t6' = Word8 -> Word8
    sbox3 Word8
    t6 in
        let t7' :: Word8
    t7' = Word8 -> Word8
    sbox4 Word8
    t7 in
        let t8' :: Word8
    t8' = Word8 -> Word8
    sbox1 Word8
    t8 in
        let y1 :: Word8
    y1 = Word8
    t1' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t3' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t4' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y2 :: Word8
    y2 = Word8
    t1' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t2' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t4' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y3 :: Word8
    y3 = Word8
    t1' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t2' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t3' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y4 :: Word8
    y4 = Word8
    t2' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t3' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t4' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' in
        let y5 :: Word8
    y5 = Word8
    t1' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t2' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y6 :: Word8
    y6 = Word8
    t2' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t3' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y7 :: Word8
    y7 = Word8
    t3' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t4' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t8' in
        let y8 :: Word8
    y8 = Word8
    t1' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t4' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t5' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t6' Word8 -> Word8 -> Word8
    forall a. Bits a => a -> a -> a
    `xor` Word8
    t7' in
        ByteString -> Word64
    w8tow64 (ByteString -> Word64) -> ByteString -> Word64
    forall a b. (a -> b) -> a -> b
    $ [Word8] -> ByteString
    B.pack [Word8
    y1, Word8
    y2, Word8
    y3, Word8
    y4, Word8
    y5, Word8
    y6, Word8
    y7, Word8
    y8]

    fl :: Word64 -> Word64 -> Word64
    fl :: Word64 -> Word64 -> Word64
    fl Word64
    fin Word64
    sk =
        let (Word32
    x1, Word32
    x2) = Word64 -> (Word32, Word32)
    w64tow32 Word64
    fin in
        let (Word32
    k1, Word32
    k2) = Word64 -> (Word32, Word32)
    w64tow32 Word64
    sk in
        let y2 :: Word32
    y2 = Word32
    x2 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` ((Word32
    x1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. Word32
    k1) Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    1) in
        let y1 :: Word32
    y1 = Word32
    x1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    y2 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32
    k2) in
        (Word32, Word32) -> Word64
    w32tow64 (Word32
    y1, Word32
    y2)

    flinv :: Word64 -> Word64 -> Word64
    flinv :: Word64 -> Word64 -> Word64
    flinv Word64
    fin Word64
    sk =
        let (Word32
    y1, Word32
    y2) = Word64 -> (Word32, Word32)
    w64tow32 Word64
    fin in
        let (Word32
    k1, Word32
    k2) = Word64 -> (Word32, Word32)
    w64tow32 Word64
    sk in
        let x1 :: Word32
    x1 = Word32
    y1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` (Word32
    y2 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .|. Word32
    k2) in
        let x2 :: Word32
    x2 = Word32
    y2 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    `xor` ((Word32
    x1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. Word32
    k1) Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `rotateL` Int
    1) in
        (Word32, Word32) -> Word64
    w32tow64 (Word32
    x1, Word32
    x2)

    {- in decrypt mode 0->17 1->16 ... -}
    getKeyK :: Mode -> Camellia -> Int -> Word64
    getKeyK :: Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    Encrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    k Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! Int
    i
    getKeyK Mode
    Decrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    k Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! (Int
    17 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    i)

    {- in decrypt mode 0->3 1->2 2->1 3->0 -}
    getKeyKe :: Mode -> Camellia -> Int -> Word64
    getKeyKe :: Mode -> Camellia -> Int -> Word64
    getKeyKe Mode
    Encrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    ke Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! Int
    i
    getKeyKe Mode
    Decrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    ke Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! (Int
    3 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    i)

    {- in decrypt mode 0->2 1->3 2->0 3->1 -}
    getKeyKw :: Mode -> Camellia -> Int -> Word64
    getKeyKw :: Mode -> Camellia -> Int -> Word64
    getKeyKw Mode
    Encrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    kw Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! Int
    i
    getKeyKw Mode
    Decrypt Camellia
    key Int
    i = Camellia -> Vector Word64
    kw Camellia
    key Vector Word64 -> Int -> Word64
    forall a. Unbox a => Vector a -> Int -> a
    ! ((Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    2) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    4)

    {- perform the following
        D2 = D2 ^ F(D1, k1);     // Round 1
        D1 = D1 ^ F(D2, k2);     // Round 2
        D2 = D2 ^ F(D1, k3);     // Round 3
        D1 = D1 ^ F(D2, k4);     // Round 4
        D2 = D2 ^ F(D1, k5);     // Round 5
        D1 = D1 ^ F(D2, k6);     // Round 6
     -}
    doBlockRound :: Mode -> Camellia -> Word64 -> Word64 -> Int -> (Word64, Word64)
    doBlockRound :: Mode -> Camellia -> Word64 -> Word64 -> Int -> (Word64, Word64)
    doBlockRound Mode
    mode Camellia
    key Word64
    d1 Word64
    d2 Int
    i =
        let r1 :: Word64
    r1 = Word64
    d2 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    d1 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    0Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 1+i -}
        let r2 :: Word64
    r2 = Word64
    d1 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    r1 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 2+i -}
        let r3 :: Word64
    r3 = Word64
    r1 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    r2 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 3+i -}
        let r4 :: Word64
    r4 = Word64
    r2 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    r3 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 4+i -}
        let r5 :: Word64
    r5 = Word64
    r3 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    r4 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 5+i -}
        let r6 :: Word64
    r6 = Word64
    r4 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` Word64 -> Word64 -> Word64
    feistel Word64
    r5 (Mode -> Camellia -> Int -> Word64
    getKeyK Mode
    mode Camellia
    key (Int
    5Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    i)) in     {- Round 6+i -}
        (Word64
    r6, Word64
    r5)

    doBlock :: Mode -> Camellia -> Word128 -> Word128
    doBlock :: Mode -> Camellia -> Word128 -> Word128
    doBlock Mode
    mode Camellia
    key Word128
    m =
        let (Word64
    d1, Word64
    d2) = Word128 -> (Word64, Word64)
    w128tow64 Word128
    m in

        let d1a :: Word64
    d1a = Word64
    d1 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Mode -> Camellia -> Int -> Word64
    getKeyKw Mode
    mode Camellia
    key Int
    0) in {- Prewhitening -}
        let d2a :: Word64
    d2a = Word64
    d2 Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Mode -> Camellia -> Int -> Word64
    getKeyKw Mode
    mode Camellia
    key Int
    1) in

        let (Word64
    d1b, Word64
    d2b) = Mode -> Camellia -> Word64 -> Word64 -> Int -> (Word64, Word64)
    doBlockRound Mode
    mode Camellia
    key Word64
    d1a Word64
    d2a Int
    0 in

        let d1c :: Word64
    d1c = Word64 -> Word64 -> Word64
    fl    Word64
    d1b (Mode -> Camellia -> Int -> Word64
    getKeyKe Mode
    mode Camellia
    key Int
    0) in {- FL -}
        let d2c :: Word64
    d2c = Word64 -> Word64 -> Word64
    flinv Word64
    d2b (Mode -> Camellia -> Int -> Word64
    getKeyKe Mode
    mode Camellia
    key Int
    1) in {- FLINV -}

        let (Word64
    d1d, Word64
    d2d) = Mode -> Camellia -> Word64 -> Word64 -> Int -> (Word64, Word64)
    doBlockRound Mode
    mode Camellia
    key Word64
    d1c Word64
    d2c Int
    6 in

        let d1e :: Word64
    d1e = Word64 -> Word64 -> Word64
    fl    Word64
    d1d (Mode -> Camellia -> Int -> Word64
    getKeyKe Mode
    mode Camellia
    key Int
    2) in {- FL -}
        let d2e :: Word64
    d2e = Word64 -> Word64 -> Word64
    flinv Word64
    d2d (Mode -> Camellia -> Int -> Word64
    getKeyKe Mode
    mode Camellia
    key Int
    3) in {- FLINV -}

        let (Word64
    d1f, Word64
    d2f) = Mode -> Camellia -> Word64 -> Word64 -> Int -> (Word64, Word64)
    doBlockRound Mode
    mode Camellia
    key Word64
    d1e Word64
    d2e Int
    12 in

        let d2g :: Word64
    d2g = Word64
    d2f Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Mode -> Camellia -> Int -> Word64
    getKeyKw Mode
    mode Camellia
    key Int
    2) in {- Postwhitening -}
        let d1g :: Word64
    d1g = Word64
    d1f Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    `xor` (Mode -> Camellia -> Int -> Word64
    getKeyKw Mode
    mode Camellia
    key Int
    3) in
        (Word64, Word64) -> Word128
    w64tow128 (Word64
    d2g, Word64
    d1g)

    {- encryption for 128 bits blocks -}
    encryptBlock :: Camellia -> Word128 -> Word128
    encryptBlock :: Camellia -> Word128 -> Word128
    encryptBlock = Mode -> Camellia -> Word128 -> Word128
    doBlock Mode
    Encrypt

    {- decryption for 128 bits blocks -}
    decryptBlock :: Camellia -> Word128 -> Word128
    decryptBlock :: Camellia -> Word128 -> Word128
    decryptBlock = Mode -> Camellia -> Word128 -> Word128
    doBlock Mode
    Decrypt

    encryptChunk :: Camellia -> B.ByteString -> B.ByteString
    encryptChunk :: Camellia -> ByteString -> ByteString
    encryptChunk Camellia
    key ByteString
    b = Word128 -> ByteString
    putWord128 (Word128 -> ByteString) -> Word128 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Camellia -> Word128 -> Word128
    encryptBlock Camellia
    key (Word128 -> Word128) -> Word128 -> Word128
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Word128
    getWord128 ByteString
    b

    decryptChunk :: Camellia -> B.ByteString -> B.ByteString
    decryptChunk :: Camellia -> ByteString -> ByteString
    decryptChunk Camellia
    key ByteString
    b = Word128 -> ByteString
    putWord128 (Word128 -> ByteString) -> Word128 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Camellia -> Word128 -> Word128
    decryptBlock Camellia
    key (Word128 -> Word128) -> Word128 -> Word128
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Word128
    getWord128 ByteString
    b

    doChunks :: (B.ByteString -> B.ByteString) -> B.ByteString -> [B.ByteString]
    doChunks :: (ByteString -> ByteString) -> ByteString -> [ByteString]
    doChunks ByteString -> ByteString
    f ByteString
    b =
        let (ByteString
    x, ByteString
    rest) = Int -> ByteString -> (ByteString, ByteString)
    B.splitAt Int
    16 ByteString
    b in
        if ByteString -> Int
    B.length ByteString
    rest Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    16
            then ByteString -> ByteString
    f ByteString
    x ByteString -> [ByteString] -> [ByteString]
    forall a. a -> [a] -> [a]
    : (ByteString -> ByteString) -> ByteString -> [ByteString]
    doChunks ByteString -> ByteString
    f ByteString
    rest
            else [ ByteString -> ByteString
    f ByteString
    x ]

    -- | Encrypts the given ByteString using the given Key
    encrypt :: Camellia     -- ^ The key to use
            -> B.ByteString -- ^ The data to encrypt
            -> B.ByteString
    encrypt :: Camellia -> ByteString -> ByteString
    encrypt Camellia
    key ByteString
    b = [ByteString] -> ByteString
    B.concat ([ByteString] -> ByteString) -> [ByteString] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> ByteString) -> ByteString -> [ByteString]
    doChunks (Camellia -> ByteString -> ByteString
    encryptChunk Camellia
    key) ByteString
    b

    -- | Decrypts the given ByteString using the given Key
    decrypt :: Camellia     -- ^ The key to use
            -> B.ByteString -- ^ The data to decrypt
            -> B.ByteString
    decrypt :: Camellia -> ByteString -> ByteString
    decrypt Camellia
    key ByteString
    b = [ByteString] -> ByteString
    B.concat ([ByteString] -> ByteString) -> [ByteString] -> ByteString
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> ByteString) -> ByteString -> [ByteString]
    doChunks (Camellia -> ByteString -> ByteString
    decryptChunk Camellia
    key) ByteString
    b