packages feed

raaz-0.3.0: implementation/ChaCha20/CPortable.hs

{-# LANGUAGE DataKinds                  #-}

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

import           Foreign.Ptr                ( castPtr )
import qualified Data.Vector.Unboxed as V

import           Raaz.Core
import           Raaz.Core.Types.Internal
import           Raaz.Primitive.ChaCha20.Internal
import           Raaz.Verse.ChaCha20.C.Portable

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

description :: String
description = "ChaCha20 Implementation in C exposed by libverse"

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

additionalBlocks :: BlockCount ChaCha20
additionalBlocks = blocksOf 1 Proxy

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

processBlocks = runBlockProcess verse_chacha20_c_portable


-- | Process the last bytes.
processLast :: BufferPtr
            -> BYTES Int
            -> Internals
            -> IO ()
processLast buf = processBlocks buf . atLeast


-- | The xchacha20Setup  does the following to the internal state
--
-- 1. Replaces the key stored in the keyCell using the hchacah20 hashing function
--
-- 2. Initialises the ivcell with the last two words in the xiv value.
--
-- As a result the internal state is ready to start encrypting using
-- the xchacha20 variant.
--
xchacha20Setup :: Nounce XChaCha20 -> Internals -> IO ()
xchacha20Setup (XNounce tup) mem = do
  verse_hchacha20_c_portable keyPtr h0 h1 h2 h3
  -- In the above step, the key gets replaced by the subkey obtained
  -- from the hchacha20 hash. We also set the ivcell appropriately
  initialise iv $ ivCell mem
  where keyPtr = castPtr $ keyCellPtr mem
        [LE h0,LE h1,LE h2, LE h3, h4, h5] = V.toList $ unsafeToVector tup
        iv  = Nounce $ unsafeFromList [0, h4, h5] :: Nounce ChaCha20


-- | Copy the key from the memory cell chacha20Mem.
copyKey :: Dest ChaCha20Mem -> Src (MemoryCell (Key ChaCha20)) -> IO ()
copyKey = copyCell . fmap keyCell

-------------- Helper function for running an iterator -----------
runBlockProcess :: ( Ptr buf ->
                     Word64  ->
                     Ptr a   ->
                     Ptr b   ->
                     Ptr c   ->
                     IO ()
                   )
                -> BufferPtr
                -> BlockCount Prim
                -> Internals
                -> IO ()
runBlockProcess func buf blks mem =
  let keyPtr     = castPtr $ keyCellPtr mem
      ivPtr      = castPtr $ ivCellPtr mem
      counterPtr = castPtr $ counterCellPtr mem
      blkPtr     = castPtr $ forgetAlignment buf
      wBlks      = toEnum  $ fromEnum blks
  in func blkPtr wBlks keyPtr ivPtr counterPtr