packages feed

raaz-0.3.0: indef/chacha20/XChaCha20/Implementation.hs

{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE MultiParamTypeClasses      #-}

module XChaCha20.Implementation where

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


import qualified Implementation as Base

name :: String
name = "x" ++ Base.name

description :: String
description = Base.description ++ " This is the XChaCha variant."

type Prim                    = XChaCha20
data Internals               = XChaCha20Mem
  { copyOfKey         :: MemoryCell (Key ChaCha20)
  , chacha20Internals :: Base.Internals
  }

type BufferAlignment         = Base.BufferAlignment
type BufferPtr               = AlignedBlockPtr BufferAlignment Prim

instance Memory Internals where
  memoryAlloc     = XChaCha20Mem <$> memoryAlloc <*> memoryAlloc
  unsafeToPointer = unsafeToPointer . copyOfKey


instance Initialisable Internals (Key XChaCha20) where
  initialise xkey = initialise xkey . copyOfKey

instance WriteAccessible Internals where
  writeAccess = writeAccess . copyOfKey
  afterWriteAdjustment = afterWriteAdjustment . copyOfKey

instance Initialisable Internals (Nounce XChaCha20) where
  initialise xnounce imem = do
    let dest = destination $ chacha20Internals imem
        src  = source $ copyOfKey imem
      in Base.copyKey dest src
    Base.xchacha20Setup xnounce $ chacha20Internals imem

instance Initialisable Internals (BlockCount XChaCha20) where
  initialise bcount = initialise bcountP . chacha20Internals
    where bcountP :: BlockCount ChaCha20
          bcountP = toEnum $ fromEnum bcount

instance Extractable Internals (BlockCount XChaCha20) where
  extract = fmap coerce . extract . chacha20Internals
    where coerce :: BlockCount ChaCha20 -> BlockCount XChaCha20
          coerce = toEnum . fromEnum

additionalBlocks :: BlockCount XChaCha20
additionalBlocks = coerce Base.additionalBlocks
    where coerce :: BlockCount Base.Prim -> BlockCount XChaCha20
          coerce = toEnum . fromEnum


processBlocks :: BufferPtr
              -> BlockCount Prim
              -> Internals
              -> IO ()
processBlocks buf bcount =
  Base.processBlocks (castPointer buf) (coerce bcount) . chacha20Internals
  where coerce :: BlockCount XChaCha20 -> BlockCount Base.Prim
        coerce = toEnum . fromEnum

-- | Process the last bytes.
processLast :: BufferPtr
            -> BYTES Int
            -> Internals
            -> IO ()
processLast buf nbytes = Base.processLast (castPointer buf) nbytes . chacha20Internals