packages feed

raaz-0.3.0: core/Raaz/Core/Primitive.hs

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

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies                #-}
{-# LANGUAGE FlexibleContexts            #-}
{-# LANGUAGE DataKinds                   #-}

module Raaz.Core.Primitive
       ( -- * Cryptographic Primtives
         Primitive(..), Key, Nounce, Block, BlockPtr, AlignedBlockPtr
       , BlockCount(..), blocksOf
       ) where

import Data.Vector.Unboxed (Unbox)
import GHC.TypeLits
import Foreign.Storable ( Storable )
import Raaz.Core.Prelude
import Raaz.Core.Types.Endian
import Raaz.Core.Types.Pointer
import Raaz.Core.Types.Tuple

----------------------- A primitive ------------------------------------


-- | Cryptographic primitives that process bulk data (like ciphers,
-- cryptographic hashes) process data in blocks. For data that is not
-- a multiple of the block size they may have some padding
-- strategy. The type class that captures an abstract block
-- cryptographic primitive.
--

class ( Unbox (WordType p)
      , EndianStore (WordType p)
      , KnownNat (WordsPerBlock p)
      ) => Primitive p where

  -- | The block which is the smallest unit of data that the primitive
  -- processes, is typically considered as an array of a particular
  -- word which is captured by the following associated type.
  type WordType p :: Type

  -- | The size of the array that forms the block. In particular, the
  -- block can be seen as an array of size `BlockArraySize p` of type
  -- `WORD p`.
  type WordsPerBlock p :: Nat

-- | The type family that captures the key of a keyed primitive.
data family Key p :: Type

-- | In addition to keys, certain primitives require nounces that can
-- be public but needs to be distinct across different uses when
-- sharing the key. The type family that captures the nounce for a
-- primitive (if it requires one).
data family Nounce p :: Type

-- | A block of the primitive.
type Block p   = Tuple (WordsPerBlock p) (WordType p)

-- | Pointer to a block of the primitive.
type BlockPtr p = Ptr (Block p)

-- | Aligned version of block pointers.

type AlignedBlockPtr n p = AlignedPtr n (Block p)


------------------- Type safe lengths in units of block ----------------

-- | Type safe message length in units of blocks of the primitive.
-- When dealing with buffer lengths for a primitive, it is often
-- better to use the type safe units `BlockCount`. Functions in the raaz
-- package that take lengths usually allow any type safe length as
-- long as they can be converted to bytes. This can avoid a lot of
-- tedious and error prone length calculations.
newtype BlockCount p = BlockCount {unBlockCount :: Int}
                     deriving (Show, Eq, Ord, Enum, Storable)

instance Semigroup (BlockCount p) where
  (<>) x y = BlockCount $ unBlockCount x + unBlockCount y
instance Monoid (BlockCount p) where
  mempty   = BlockCount 0
  mappend  = (<>)


instance Primitive p => LengthUnit (BlockCount p) where
  inBytes p@(BlockCount x) = toEnum x * nWords p * wordSize p
    where wordSize = sizeOf . proxyWT
          nWords   = toEnum . fromEnum . natVal . proxyWPB
          proxyWT :: Primitive p => BlockCount p -> Proxy (WordType p)
          proxyWT  = const Proxy
          proxyWPB   :: Primitive p => BlockCount p -> Proxy (WordsPerBlock p)
          proxyWPB = const Proxy


-- | The expression @n `blocksOf` primProxy@ specifies the message
-- lengths in units of the block length of the primitive whose proxy
-- is @primProxy@. This expression is sometimes required to make the
-- type checker happy.
blocksOf :: Int -> Proxy p -> BlockCount p
blocksOf n _ = BlockCount n