packages feed

raaz-0.3.0: core/Raaz/Primitive/ChaCha20/Internal.hs

{-# LANGUAGE DataKinds                        #-}
{-# LANGUAGE GeneralizedNewtypeDeriving       #-}
{-# LANGUAGE FlexibleInstances                #-}
{-# LANGUAGE MultiParamTypeClasses            #-}
{-# LANGUAGE TypeFamilies                     #-}

{- HLINT ignore "Unused LANGUAGE pragma" -}


-- |
--
-- Module      : Raaz.Primitive.ChaCha20.Internal
-- Description : Internal module for ChaCha20 cipher.
-- Copyright   : (c) Piyush P Kurur, 2019
-- License     : Apache-2.0 OR BSD-3-Clause
-- Maintainer  : Piyush P Kurur <ppk@iitpkd.ac.in>
-- Stability   : experimental
--

module Raaz.Primitive.ChaCha20.Internal
       ( -- * ChaCha20 cipher
         -- $chacha20$
         ChaCha20(..), XChaCha20(..)
       , Key(..), Nounce(..)
       , ChaCha20Mem(..)
       , keyCellPtr, ivCellPtr, counterCellPtr
       ) where

import Foreign.Storable
import Raaz.Core

-- $chacha20$
--
-- This module defines the ChaCha20 ciphers and the memory element
-- used by a typical implementation. The variant of Chacha20 that we
-- support is the IETF version described in RFC 7538 with 32-bit
-- (4-byte) counter and 96-bit (12-byte) IV.

-- | The type associated with the ChaCha20 cipher.
data ChaCha20 = ChaCha20

-- | The type associated with the XChaCha20 variant.
data XChaCha20 = XChaCha20

type WORD     = LE Word32
type KEY      = Tuple 8 WORD

instance Primitive ChaCha20 where
  type WordType      ChaCha20 = WORD
  type WordsPerBlock ChaCha20 = 16

instance Primitive XChaCha20 where
  type WordType      XChaCha20  = WORD
  type WordsPerBlock XChaCha20  = 16


newtype instance Key     ChaCha20 = Key KEY
  deriving (Storable, EndianStore, Equality, Eq)

newtype instance Nounce  ChaCha20 = Nounce  (Tuple 3 WORD)
  deriving (Storable, EndianStore, Equality, Eq)

instance Encodable (Key     ChaCha20)
instance Encodable (Nounce  ChaCha20)

instance Show (Key ChaCha20) where
  show = showBase16

instance Show (Nounce ChaCha20) where
  show = showBase16


instance IsString (Key ChaCha20) where
  fromString = fromBase16


instance IsString (Nounce ChaCha20) where
  fromString = fromBase16


newtype instance Key     XChaCha20 = XKey KEY
  deriving (Storable, EndianStore)
newtype instance Nounce  XChaCha20 = XNounce  (Tuple 6 WORD)
  deriving (Storable, EndianStore)

instance Encodable (Key     XChaCha20)
instance Encodable (Nounce  XChaCha20)

instance Show (Key XChaCha20) where
  show = showBase16

instance Show (Nounce XChaCha20) where
  show = showBase16


instance IsString (Key XChaCha20) where
  fromString = fromBase16


instance IsString (Nounce XChaCha20) where
  fromString = fromBase16

---------- Memory for ChaCha20 implementations  ------------------
-- | The memory element used by chacha20. This memory is an instance
-- of `WriteAccessible` where the key portion of the memory can be
-- written into.
data ChaCha20Mem = ChaCha20Mem { keyCell      :: MemoryCell (Key     ChaCha20)
                               , ivCell       :: MemoryCell (Nounce  ChaCha20)
                               , counterCell  :: MemoryCell WORD
                               }

-- | The pointer into the chacha memory where the key is stored.
keyCellPtr :: ChaCha20Mem -> Ptr (Key ChaCha20)
keyCellPtr = unsafeGetCellPointer . keyCell

-- | The pointer into the chacha memory where the iv is stored.
ivCellPtr :: ChaCha20Mem -> Ptr (Nounce ChaCha20)
ivCellPtr = unsafeGetCellPointer . ivCell

-- | The pointer in the chacha memory where the counter is stored.
counterCellPtr :: ChaCha20Mem -> Ptr WORD
counterCellPtr = unsafeGetCellPointer . counterCell

instance Initialisable  (MemoryCell (Key ChaCha20)) (Key XChaCha20) where
  initialise = initialise . coerce
    where coerce (XKey k) = Key k

instance Memory ChaCha20Mem where
  memoryAlloc     = ChaCha20Mem <$> memoryAlloc <*> memoryAlloc <*> memoryAlloc
  unsafeToPointer = unsafeToPointer . keyCell

instance Initialisable ChaCha20Mem (Key ChaCha20) where
  initialise key = initialise key . keyCell

instance Initialisable ChaCha20Mem (Nounce ChaCha20)  where
  initialise nounce = initialise nounce . ivCell

instance Initialisable ChaCha20Mem (BlockCount ChaCha20) where
  initialise bcount = initialise (conv bcount) . counterCell
    where conv :: BlockCount ChaCha20 -> WORD
          conv = toEnum . fromEnum

instance Extractable ChaCha20Mem (BlockCount ChaCha20) where
  extract = fmap conv . extract  . counterCell
    where conv :: WORD -> BlockCount ChaCha20
          conv = toEnum . fromEnum

-- | Writes into the key portion.
instance WriteAccessible ChaCha20Mem where
  writeAccess = writeAccess . keyCell
  afterWriteAdjustment = afterWriteAdjustment . keyCell