{-# 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 Prim
additionalBlocks = Int -> Proxy Prim -> BlockCount Prim
forall p. Int -> Proxy p -> BlockCount p
blocksOf Int
1 Proxy Prim
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 Prim -> Internals -> IO ()
processBlocks BufferPtr
buf BlockCount Prim
blks Internals
mem =
  let keyPtr :: Ptr (Key Prim)
keyPtr     = Internals -> Ptr (Key Prim)
keyCellPtr Internals
mem
      ivPtr :: Ptr (Nounce Prim)
ivPtr      = Internals -> Ptr (Nounce Prim)
ivCellPtr Internals
mem
      counterPtr :: Ptr WORD
counterPtr = Internals -> Ptr WORD
counterCellPtr Internals
mem
  in BufferPtr
-> BlockCount Prim
-> Ptr (Key Prim)
-> Ptr (Nounce Prim)
-> Ptr (WordType Prim)
-> IO ()
c_chacha20_block BufferPtr
buf BlockCount Prim
blks Ptr (Key Prim)
keyPtr Ptr (Nounce Prim)
ivPtr Ptr (WordType Prim)
Ptr WORD
counterPtr

-- | Process the last bytes.
processLast :: BufferPtr
            -> BYTES Int
            -> Internals
            -> IO ()
processLast :: BufferPtr -> BYTES Int -> Internals -> IO ()
processLast BufferPtr
buf = BufferPtr -> BlockCount Prim -> Internals -> IO ()
processBlocks BufferPtr
buf (BlockCount Prim -> Internals -> IO ())
-> (BYTES Int -> BlockCount Prim)
-> BYTES Int
-> Internals
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BYTES Int -> BlockCount Prim
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 Prim
reseedAfter = Int -> Proxy Prim -> BlockCount Prim
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 Prim
forall {k} (t :: k). Proxy t
Proxy :: Proxy Prim)

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

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