{-# LANGUAGE ForeignFunctionInterface         #-}
{-# LANGUAGE MultiParamTypeClasses            #-}
{-# LANGUAGE FlexibleInstances                #-}
{-# LANGUAGE DataKinds                        #-}

-- | Portable C implementation of ChaCha20.
module Raaz.Cipher.ChaCha20.Implementation.CPortable
       ( implementation, chacha20Random
       ) where

import Control.Monad.IO.Class   ( liftIO )
import Foreign.Ptr              ( Ptr    )

import Raaz.Core
import Raaz.Cipher.Internal
import Raaz.Cipher.ChaCha20.Internal

-- | The portable c implementation of chacha20 cipher.
implementation :: SomeCipherI ChaCha20
implementation  = SomeCipherI chacha20Portable

-- | Chacha20 block transformation.
foreign import ccall unsafe
  "raaz/cipher/chacha20/cportable.h raazChaCha20Block"
  c_chacha20_block :: Pointer      -- Message
                   -> Int          -- number of blocks
                   -> Ptr KEY      -- key
                   -> Ptr IV       -- iv
                   -> Ptr Counter  -- Counter value
                   -> IO ()




-- | Encrypting/Decrypting a block of chacha20.
chacha20Block :: Pointer -> BLOCKS ChaCha20 -> MT ChaCha20Mem ()
chacha20Block msgPtr nblocks = do keyPtr <- onSubMemory keyCell     getCellPointer
                                  ivPtr  <- onSubMemory ivCell      getCellPointer
                                  ctrPtr <- onSubMemory counterCell getCellPointer
                                  liftIO $ c_chacha20_block msgPtr (fromEnum nblocks) keyPtr ivPtr ctrPtr

-- | The chacha20 randomness generator.
chacha20Random :: Pointer -> BLOCKS ChaCha20 -> MT ChaCha20Mem ()
chacha20Random = chacha20Block

---------------------- DANGEROUS CODE --------------------------------------

-- | The chacha20 randomness generator. We have set the alignment to
-- 32 because this allows gcc to further optimise the implementation.
chacha20Portable :: CipherI ChaCha20 ChaCha20Mem ChaCha20Mem
chacha20Portable = makeCipherI
                   "chacha20-cportable"
                   "Implementation of the chacha20 stream cipher (RFC7539)"
                   chacha20Block
                   32