{-# LANGUAGE DataKinds                        #-}
{-# LANGUAGE GeneralizedNewtypeDeriving       #-}
{-# LANGUAGE FlexibleInstances                #-}
{-# LANGUAGE MultiParamTypeClasses            #-}
{-# LANGUAGE TypeFamilies                     #-}

-- | The internals of ChaCha20 ciphers.
module Raaz.Cipher.ChaCha20.Internal
       ( ChaCha20(..), WORD, Counter(..), IV(..), KEY(..), ChaCha20Mem(..)
       ) where

import Control.Applicative
import Data.Word
import Data.String
import Foreign.Storable
import Prelude


import Raaz.Core
import Raaz.Cipher.Internal

-- | The chacha20 stream cipher.


-- | The word type
type WORD     = LE Word32

-- | The IV for the chacha20
newtype IV       = IV (Tuple 3 (LE Word32))     deriving (Ptr b -> Int -> IO IV
Ptr b -> Int -> IV -> IO ()
Ptr IV -> IO IV
Ptr IV -> Int -> IO IV
Ptr IV -> Int -> IV -> IO ()
Ptr IV -> IV -> IO ()
IV -> Int
(IV -> Int)
-> (IV -> Int)
-> (Ptr IV -> Int -> IO IV)
-> (Ptr IV -> Int -> IV -> IO ())
-> (forall b. Ptr b -> Int -> IO IV)
-> (forall b. Ptr b -> Int -> IV -> IO ())
-> (Ptr IV -> IO IV)
-> (Ptr IV -> IV -> IO ())
-> Storable IV
forall b. Ptr b -> Int -> IO IV
forall b. Ptr b -> Int -> IV -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr IV -> IV -> IO ()
$cpoke :: Ptr IV -> IV -> IO ()
peek :: Ptr IV -> IO IV
$cpeek :: Ptr IV -> IO IV
pokeByteOff :: Ptr b -> Int -> IV -> IO ()
$cpokeByteOff :: forall b. Ptr b -> Int -> IV -> IO ()
peekByteOff :: Ptr b -> Int -> IO IV
$cpeekByteOff :: forall b. Ptr b -> Int -> IO IV
pokeElemOff :: Ptr IV -> Int -> IV -> IO ()
$cpokeElemOff :: Ptr IV -> Int -> IV -> IO ()
peekElemOff :: Ptr IV -> Int -> IO IV
$cpeekElemOff :: Ptr IV -> Int -> IO IV
alignment :: IV -> Int
$calignment :: IV -> Int
sizeOf :: IV -> Int
$csizeOf :: IV -> Int
Storable, Storable IV
Ptr IV -> IO IV
Ptr IV -> Int -> IO ()
Ptr IV -> IV -> IO ()
Storable IV
-> (Ptr IV -> IV -> IO ())
-> (Ptr IV -> IO IV)
-> (Ptr IV -> Int -> IO ())
-> EndianStore IV
forall w.
Storable w
-> (Ptr w -> w -> IO ())
-> (Ptr w -> IO w)
-> (Ptr w -> Int -> IO ())
-> EndianStore w
adjustEndian :: Ptr IV -> Int -> IO ()
$cadjustEndian :: Ptr IV -> Int -> IO ()
load :: Ptr IV -> IO IV
$cload :: Ptr IV -> IO IV
store :: Ptr IV -> IV -> IO ()
$cstore :: Ptr IV -> IV -> IO ()
$cp1EndianStore :: Storable IV
EndianStore)

instance Encodable IV

instance Show IV where
  show :: IV -> String
show = IV -> String
forall a. Encodable a => a -> String
showBase16
instance IsString IV where
  fromString :: String -> IV
fromString = String -> IV
forall a. Encodable a => String -> a
fromBase16

-- | The counter type for chacha20
newtype Counter  = Counter (LE Word32) deriving (Integer -> Counter
Counter -> Counter
Counter -> Counter -> Counter
(Counter -> Counter -> Counter)
-> (Counter -> Counter -> Counter)
-> (Counter -> Counter -> Counter)
-> (Counter -> Counter)
-> (Counter -> Counter)
-> (Counter -> Counter)
-> (Integer -> Counter)
-> Num Counter
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Counter
$cfromInteger :: Integer -> Counter
signum :: Counter -> Counter
$csignum :: Counter -> Counter
abs :: Counter -> Counter
$cabs :: Counter -> Counter
negate :: Counter -> Counter
$cnegate :: Counter -> Counter
* :: Counter -> Counter -> Counter
$c* :: Counter -> Counter -> Counter
- :: Counter -> Counter -> Counter
$c- :: Counter -> Counter -> Counter
+ :: Counter -> Counter -> Counter
$c+ :: Counter -> Counter -> Counter
Num, Ptr b -> Int -> IO Counter
Ptr b -> Int -> Counter -> IO ()
Ptr Counter -> IO Counter
Ptr Counter -> Int -> IO Counter
Ptr Counter -> Int -> Counter -> IO ()
Ptr Counter -> Counter -> IO ()
Counter -> Int
(Counter -> Int)
-> (Counter -> Int)
-> (Ptr Counter -> Int -> IO Counter)
-> (Ptr Counter -> Int -> Counter -> IO ())
-> (forall b. Ptr b -> Int -> IO Counter)
-> (forall b. Ptr b -> Int -> Counter -> IO ())
-> (Ptr Counter -> IO Counter)
-> (Ptr Counter -> Counter -> IO ())
-> Storable Counter
forall b. Ptr b -> Int -> IO Counter
forall b. Ptr b -> Int -> Counter -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr Counter -> Counter -> IO ()
$cpoke :: Ptr Counter -> Counter -> IO ()
peek :: Ptr Counter -> IO Counter
$cpeek :: Ptr Counter -> IO Counter
pokeByteOff :: Ptr b -> Int -> Counter -> IO ()
$cpokeByteOff :: forall b. Ptr b -> Int -> Counter -> IO ()
peekByteOff :: Ptr b -> Int -> IO Counter
$cpeekByteOff :: forall b. Ptr b -> Int -> IO Counter
pokeElemOff :: Ptr Counter -> Int -> Counter -> IO ()
$cpokeElemOff :: Ptr Counter -> Int -> Counter -> IO ()
peekElemOff :: Ptr Counter -> Int -> IO Counter
$cpeekElemOff :: Ptr Counter -> Int -> IO Counter
alignment :: Counter -> Int
$calignment :: Counter -> Int
sizeOf :: Counter -> Int
$csizeOf :: Counter -> Int
Storable, Storable Counter
Ptr Counter -> IO Counter
Ptr Counter -> Int -> IO ()
Ptr Counter -> Counter -> IO ()
Storable Counter
-> (Ptr Counter -> Counter -> IO ())
-> (Ptr Counter -> IO Counter)
-> (Ptr Counter -> Int -> IO ())
-> EndianStore Counter
forall w.
Storable w
-> (Ptr w -> w -> IO ())
-> (Ptr w -> IO w)
-> (Ptr w -> Int -> IO ())
-> EndianStore w
adjustEndian :: Ptr Counter -> Int -> IO ()
$cadjustEndian :: Ptr Counter -> Int -> IO ()
load :: Ptr Counter -> IO Counter
$cload :: Ptr Counter -> IO Counter
store :: Ptr Counter -> Counter -> IO ()
$cstore :: Ptr Counter -> Counter -> IO ()
$cp1EndianStore :: Storable Counter
EndianStore, Int -> Counter -> ShowS
[Counter] -> ShowS
Counter -> String
(Int -> Counter -> ShowS)
-> (Counter -> String) -> ([Counter] -> ShowS) -> Show Counter
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Counter] -> ShowS
$cshowList :: [Counter] -> ShowS
show :: Counter -> String
$cshow :: Counter -> String
showsPrec :: Int -> Counter -> ShowS
$cshowsPrec :: Int -> Counter -> ShowS
Show, Counter -> Counter -> Bool
(Counter -> Counter -> Bool)
-> (Counter -> Counter -> Bool) -> Eq Counter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Counter -> Counter -> Bool
$c/= :: Counter -> Counter -> Bool
== :: Counter -> Counter -> Bool
$c== :: Counter -> Counter -> Bool
Eq, Eq Counter
Eq Counter
-> (Counter -> Counter -> Ordering)
-> (Counter -> Counter -> Bool)
-> (Counter -> Counter -> Bool)
-> (Counter -> Counter -> Bool)
-> (Counter -> Counter -> Bool)
-> (Counter -> Counter -> Counter)
-> (Counter -> Counter -> Counter)
-> Ord Counter
Counter -> Counter -> Bool
Counter -> Counter -> Ordering
Counter -> Counter -> Counter
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Counter -> Counter -> Counter
$cmin :: Counter -> Counter -> Counter
max :: Counter -> Counter -> Counter
$cmax :: Counter -> Counter -> Counter
>= :: Counter -> Counter -> Bool
$c>= :: Counter -> Counter -> Bool
> :: Counter -> Counter -> Bool
$c> :: Counter -> Counter -> Bool
<= :: Counter -> Counter -> Bool
$c<= :: Counter -> Counter -> Bool
< :: Counter -> Counter -> Bool
$c< :: Counter -> Counter -> Bool
compare :: Counter -> Counter -> Ordering
$ccompare :: Counter -> Counter -> Ordering
$cp1Ord :: Eq Counter
Ord)


-- | The key type.
newtype KEY      = ChaCha20Key (Tuple 8 WORD) deriving (Ptr b -> Int -> IO KEY
Ptr b -> Int -> KEY -> IO ()
Ptr KEY -> IO KEY
Ptr KEY -> Int -> IO KEY
Ptr KEY -> Int -> KEY -> IO ()
Ptr KEY -> KEY -> IO ()
KEY -> Int
(KEY -> Int)
-> (KEY -> Int)
-> (Ptr KEY -> Int -> IO KEY)
-> (Ptr KEY -> Int -> KEY -> IO ())
-> (forall b. Ptr b -> Int -> IO KEY)
-> (forall b. Ptr b -> Int -> KEY -> IO ())
-> (Ptr KEY -> IO KEY)
-> (Ptr KEY -> KEY -> IO ())
-> Storable KEY
forall b. Ptr b -> Int -> IO KEY
forall b. Ptr b -> Int -> KEY -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
poke :: Ptr KEY -> KEY -> IO ()
$cpoke :: Ptr KEY -> KEY -> IO ()
peek :: Ptr KEY -> IO KEY
$cpeek :: Ptr KEY -> IO KEY
pokeByteOff :: Ptr b -> Int -> KEY -> IO ()
$cpokeByteOff :: forall b. Ptr b -> Int -> KEY -> IO ()
peekByteOff :: Ptr b -> Int -> IO KEY
$cpeekByteOff :: forall b. Ptr b -> Int -> IO KEY
pokeElemOff :: Ptr KEY -> Int -> KEY -> IO ()
$cpokeElemOff :: Ptr KEY -> Int -> KEY -> IO ()
peekElemOff :: Ptr KEY -> Int -> IO KEY
$cpeekElemOff :: Ptr KEY -> Int -> IO KEY
alignment :: KEY -> Int
$calignment :: KEY -> Int
sizeOf :: KEY -> Int
$csizeOf :: KEY -> Int
Storable, Storable KEY
Ptr KEY -> IO KEY
Ptr KEY -> Int -> IO ()
Ptr KEY -> KEY -> IO ()
Storable KEY
-> (Ptr KEY -> KEY -> IO ())
-> (Ptr KEY -> IO KEY)
-> (Ptr KEY -> Int -> IO ())
-> EndianStore KEY
forall w.
Storable w
-> (Ptr w -> w -> IO ())
-> (Ptr w -> IO w)
-> (Ptr w -> Int -> IO ())
-> EndianStore w
adjustEndian :: Ptr KEY -> Int -> IO ()
$cadjustEndian :: Ptr KEY -> Int -> IO ()
load :: Ptr KEY -> IO KEY
$cload :: Ptr KEY -> IO KEY
store :: Ptr KEY -> KEY -> IO ()
$cstore :: Ptr KEY -> KEY -> IO ()
$cp1EndianStore :: Storable KEY
EndianStore)

instance Encodable KEY

instance Show KEY where
  show :: KEY -> String
show = KEY -> String
forall a. Encodable a => a -> String
showBase16

instance IsString KEY where
  fromString :: String -> KEY
fromString = String -> KEY
forall a. Encodable a => String -> a
fromBase16

-- | The type associated with the ChaCha20 cipher.
data ChaCha20 = ChaCha20

instance Primitive ChaCha20 where
  blockSize :: ChaCha20 -> BYTES Int
blockSize ChaCha20
_ = Int -> BYTES Int
forall a. a -> BYTES a
BYTES Int
64
  type Implementation ChaCha20 = SomeCipherI ChaCha20

-- | The key for ChaCha20.
type instance Key ChaCha20 = (KEY, IV, Counter)

instance Describable ChaCha20 where
  name :: ChaCha20 -> String
name        ChaCha20
_ = String
"chacha20"
  description :: ChaCha20 -> String
description ChaCha20
_ = String
"The ChaCha20 cipher"

instance Cipher ChaCha20

instance StreamCipher ChaCha20



---------- Memory for ChaCha20 implementations  ------------------
-- | chacha20 memory
data ChaCha20Mem = ChaCha20Mem { ChaCha20Mem -> MemoryCell KEY
keyCell      :: MemoryCell KEY
                               , ChaCha20Mem -> MemoryCell IV
ivCell       :: MemoryCell IV
                               , ChaCha20Mem -> MemoryCell Counter
counterCell  :: MemoryCell Counter
                               }


instance Memory ChaCha20Mem where
  memoryAlloc :: Alloc ChaCha20Mem
memoryAlloc     = MemoryCell KEY
-> MemoryCell IV -> MemoryCell Counter -> ChaCha20Mem
ChaCha20Mem (MemoryCell KEY
 -> MemoryCell IV -> MemoryCell Counter -> ChaCha20Mem)
-> TwistRF AllocField (BYTES Int) (MemoryCell KEY)
-> TwistRF
     AllocField
     (BYTES Int)
     (MemoryCell IV -> MemoryCell Counter -> ChaCha20Mem)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TwistRF AllocField (BYTES Int) (MemoryCell KEY)
forall m. Memory m => Alloc m
memoryAlloc TwistRF
  AllocField
  (BYTES Int)
  (MemoryCell IV -> MemoryCell Counter -> ChaCha20Mem)
-> TwistRF AllocField (BYTES Int) (MemoryCell IV)
-> TwistRF
     AllocField (BYTES Int) (MemoryCell Counter -> ChaCha20Mem)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TwistRF AllocField (BYTES Int) (MemoryCell IV)
forall m. Memory m => Alloc m
memoryAlloc TwistRF AllocField (BYTES Int) (MemoryCell Counter -> ChaCha20Mem)
-> TwistRF AllocField (BYTES Int) (MemoryCell Counter)
-> Alloc ChaCha20Mem
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TwistRF AllocField (BYTES Int) (MemoryCell Counter)
forall m. Memory m => Alloc m
memoryAlloc
  unsafeToPointer :: ChaCha20Mem -> Pointer
unsafeToPointer = MemoryCell KEY -> Pointer
forall m. Memory m => m -> Pointer
unsafeToPointer (MemoryCell KEY -> Pointer)
-> (ChaCha20Mem -> MemoryCell KEY) -> ChaCha20Mem -> Pointer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ChaCha20Mem -> MemoryCell KEY
keyCell

instance Initialisable ChaCha20Mem (KEY, IV, Counter) where
  initialise :: (KEY, IV, Counter) -> MT ChaCha20Mem ()
initialise (KEY
k,IV
iv,Counter
ctr) = do (ChaCha20Mem -> MemoryCell KEY)
-> MT (MemoryCell KEY) () -> MT ChaCha20Mem ()
forall (mT :: * -> * -> *) mem submem a.
MemoryThread mT =>
(mem -> submem) -> mT submem a -> mT mem a
onSubMemory ChaCha20Mem -> MemoryCell KEY
keyCell     (MT (MemoryCell KEY) () -> MT ChaCha20Mem ())
-> MT (MemoryCell KEY) () -> MT ChaCha20Mem ()
forall a b. (a -> b) -> a -> b
$ KEY -> MT (MemoryCell KEY) ()
forall m v. Initialisable m v => v -> MT m ()
initialise KEY
k
                             (ChaCha20Mem -> MemoryCell IV)
-> MT (MemoryCell IV) () -> MT ChaCha20Mem ()
forall (mT :: * -> * -> *) mem submem a.
MemoryThread mT =>
(mem -> submem) -> mT submem a -> mT mem a
onSubMemory ChaCha20Mem -> MemoryCell IV
ivCell      (MT (MemoryCell IV) () -> MT ChaCha20Mem ())
-> MT (MemoryCell IV) () -> MT ChaCha20Mem ()
forall a b. (a -> b) -> a -> b
$ IV -> MT (MemoryCell IV) ()
forall m v. Initialisable m v => v -> MT m ()
initialise IV
iv
                             (ChaCha20Mem -> MemoryCell Counter)
-> MT (MemoryCell Counter) () -> MT ChaCha20Mem ()
forall (mT :: * -> * -> *) mem submem a.
MemoryThread mT =>
(mem -> submem) -> mT submem a -> mT mem a
onSubMemory ChaCha20Mem -> MemoryCell Counter
counterCell (MT (MemoryCell Counter) () -> MT ChaCha20Mem ())
-> MT (MemoryCell Counter) () -> MT ChaCha20Mem ()
forall a b. (a -> b) -> a -> b
$ Counter -> MT (MemoryCell Counter) ()
forall m v. Initialisable m v => v -> MT m ()
initialise Counter
ctr


instance Initialisable ChaCha20Mem (KEY, IV) where
  initialise :: (KEY, IV) -> MT ChaCha20Mem ()
initialise (KEY
k, IV
iv) = (KEY, IV, Counter) -> MT ChaCha20Mem ()
forall m v. Initialisable m v => v -> MT m ()
initialise (KEY
k, IV
iv, Counter
0 :: Counter)