packages feed

raaz-0.3.0: implementation/Blake2b/CPortable.hs

{-# LANGUAGE DataKinds                  #-}

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


import Foreign.Ptr                ( castPtr      )

import Raaz.Core
import Raaz.Core.Transfer.Unsafe
import Raaz.Core.Types.Internal
import Raaz.Primitive.HashMemory
import Raaz.Primitive.Blake2.Internal
import Raaz.Verse.Blake2b.C.Portable

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

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

type Prim                    = Blake2b
type Internals               = Blake2bMem
type BufferAlignment         = 32
type BufferPtr               = AlignedBlockPtr BufferAlignment Prim

additionalBlocks :: BlockCount Blake2b
additionalBlocks = blocksOf 1 Proxy


processBlocks :: BufferPtr
              -> BlockCount Blake2b
              -> Blake2bMem
              -> IO ()

processBlocks buf blks b2bmem =
  let uPtr   = castPtr $ uLengthCellPointer b2bmem
      lPtr   = castPtr $ lLengthCellPointer b2bmem
      hshPtr = castPtr $ hashCell128Pointer b2bmem
      --
      -- Type coersions to the appropriate type.
      --
      wblks  = toEnum  $ fromEnum blks
      blkPtr = castPtr $ forgetAlignment buf
  in verse_blake2b_c_portable_iter blkPtr wblks uPtr lPtr hshPtr


-- | Process the last bytes. The last block of the message (whether it
-- is padded or not) should necessarily be processed by the
-- processLast function as one needs to set the finalisation flag for
-- it.
--
-- Let us consider two cases.
--
-- 1. The message is empty. In which case the padding is 1-block
--    size. This needs to be processed as the last block
--
-- 2. If the message is non-empty then the padded message is the least
--    multiple @n@ of block size that is greater than or equal to the
--    input and hence is at least 1 block in size. Therefore, we
--    should be compressing a total @n-1@ blocks using the block
--    compression function at the last block using the finalisation
--    flags.
--
processLast :: BufferPtr
            -> BYTES Int
            -> Blake2bMem
            -> IO ()
processLast buf nbytes b2bmem = do
  unsafeTransfer padding $ forgetAlignment buf  -- pad the message
  processBlocks buf nBlocks b2bmem              -- process all but the last block
  --
  -- Handle the last block
  --
  BYTES u  <- getULength b2bmem
  BYTES l  <- getLLength b2bmem
  let hshPtr = castPtr $ hashCell128Pointer b2bmem
    in verse_blake2b_c_portable_last lastBlockPtr remBytes u l f0 f1 hshPtr

  where padding      = blake2Pad (Proxy :: Proxy Blake2b) nbytes
        nBlocks      = atMost (transferSize padding) `mappend` toEnum (-1)
                                           -- all but the last block
        remBytes     = toEnum $ fromEnum $ nbytes - inBytes nBlocks
                                           -- Actual bytes in the last block.
        lastBlockPtr = castPtr (forgetAlignment buf `movePtr` nBlocks)
        --
        -- Finalisation FLAGS
        --
        f0 = complement 0
        f1 = 0