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