{-# LANGUAGE ForeignFunctionInterface   #-}
{-# LANGUAGE DataKinds                  #-}


-- | The portable C-implementation of Blake2b.
module ChaCha20.CHandWritten where

import Raaz.Core
import Raaz.Core.Types.Internal
import Raaz.Primitive.ChaCha20.Internal


name :: String
name :: String
name = String
"chacha20-c-handwritten"

description :: String
description :: String
description = String
"Hand written ChaCha20 Implementation using portable C"

type Prim                    = ChaCha20
type Internals               = ChaCha20Mem
type BufferAlignment         = 32
type BufferPtr               = AlignedBlockPtr BufferAlignment Prim

additionalBlocks :: BlockCount ChaCha20
additionalBlocks :: BlockCount ChaCha20
additionalBlocks = Int -> Proxy ChaCha20 -> BlockCount ChaCha20
forall p. Int -> Proxy p -> BlockCount p
blocksOf Int
1 Proxy ChaCha20
forall k (t :: k). Proxy t
Proxy


------------------------ The foreign function calls  ---------------------

-- | Chacha20 block transformation.
foreign import ccall unsafe
  "raaz/cipher/chacha20/cportable.h raazChaCha20Block"
  c_chacha20_block :: BufferPtr -- message
                   -> BlockCount ChaCha20                -- number of blocks
                   -> Ptr (Key ChaCha20)             -- key
                   -> Ptr (Nounce ChaCha20)          -- iv
                   -> Ptr (WordType ChaCha20)
                   -> IO ()

processBlocks :: BufferPtr
              -> BlockCount Prim
              -> Internals
              -> IO ()

processBlocks :: BufferPtr -> BlockCount ChaCha20 -> Internals -> IO ()
processBlocks BufferPtr
buf BlockCount ChaCha20
blks Internals
mem =
  let keyPtr :: Ptr (Key ChaCha20)
keyPtr     = Internals -> Ptr (Key ChaCha20)
keyCellPtr Internals
mem
      ivPtr :: Ptr (Nounce ChaCha20)
ivPtr      = Internals -> Ptr (Nounce ChaCha20)
ivCellPtr Internals
mem
      counterPtr :: Ptr WORD
counterPtr = Internals -> Ptr WORD
counterCellPtr Internals
mem
  in BufferPtr
-> BlockCount ChaCha20
-> Ptr (Key ChaCha20)
-> Ptr (Nounce ChaCha20)
-> Ptr (WordType ChaCha20)
-> IO ()
c_chacha20_block BufferPtr
buf BlockCount ChaCha20
blks Ptr (Key ChaCha20)
keyPtr Ptr (Nounce ChaCha20)
ivPtr Ptr (WordType ChaCha20)
Ptr WORD
counterPtr

-- | Process the last bytes.
processLast :: BufferPtr
            -> BYTES Int
            -> Internals
            -> IO ()
processLast :: BufferPtr -> BYTES Int -> Internals -> IO ()
processLast BufferPtr
buf = BufferPtr -> BlockCount ChaCha20 -> Internals -> IO ()
processBlocks BufferPtr
buf (BlockCount ChaCha20 -> Internals -> IO ())
-> (BYTES Int -> BlockCount ChaCha20)
-> BYTES Int
-> Internals
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BYTES Int -> BlockCount ChaCha20
forall src dest. (LengthUnit src, LengthUnit dest) => src -> dest
atLeast

-- | The number of blocks of the cipher that is generated in one go
-- encoded as a type level nat.
type RandomBufferSize = 16


-- | How many blocks of the primitive to generated before re-seeding.
reseedAfter :: BlockCount Prim
reseedAfter :: BlockCount ChaCha20
reseedAfter = Int -> Proxy ChaCha20 -> BlockCount ChaCha20
forall p. Int -> Proxy p -> BlockCount p
blocksOf (Int
1024 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1024 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
1024) (Proxy ChaCha20
forall k (t :: k). Proxy t
Proxy :: Proxy Prim)

randomBlocks :: BufferPtr
             -> BlockCount Prim
             -> Internals
             -> IO ()

randomBlocks :: BufferPtr -> BlockCount ChaCha20 -> Internals -> IO ()
randomBlocks  = BufferPtr -> BlockCount ChaCha20 -> Internals -> IO ()
processBlocks