raaz-0.3.0: core/Raaz/Primitive/Sha2/Internal.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# CFILES raaz/hash/sha1/portable.c #-}
-- |
--
-- Module : Raaz.Primitive.Sha2.Internal
-- Description : Internal modules for sha2 family of hashes.
-- 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.Sha2.Internal
( -- * The sha2 types
Sha512, Sha256
, Sha512Mem, Sha256Mem
, process512Last
, process256Last
) where
import Data.Vector.Unboxed ( Unbox )
import Foreign.Storable ( Storable(..) )
import GHC.TypeLits
import Raaz.Core
import Raaz.Core.Transfer.Unsafe
import Raaz.Primitive.HashMemory
----------------------------- The blake2 type ---------------------------------
-- | The Sha2 type.
newtype Sha2 w = Sha2 (Tuple 8 w)
deriving (Eq, Equality, Storable, EndianStore)
instance ( Unbox w
, EndianStore w
) => Primitive (Sha2 w) where
type WordType (Sha2 w) = w
type WordsPerBlock (Sha2 w) = 16
instance (Unbox w, EndianStore w) => Encodable (Sha2 w)
instance (EndianStore w, Unbox w) => IsString (Sha2 w) where
fromString = fromBase16
instance (EndianStore w, Unbox w) => Show (Sha2 w) where
show = showBase16
-- | The Sha512 cryptographic hash.
type Sha512 = Sha2 (BE Word64)
-- | The Sha256 cryptographic hash.
type Sha256 = Sha2 (BE Word32)
-- | The initial value to start the blake2b hashing. This is equal to
-- the iv `xor` the parameter block.
sha512Init :: Sha512
sha512Init = Sha2 $ unsafeFromList [ 0x6a09e667f3bcc908
, 0xbb67ae8584caa73b
, 0x3c6ef372fe94f82b
, 0xa54ff53a5f1d36f1
, 0x510e527fade682d1
, 0x9b05688c2b3e6c1f
, 0x1f83d9abfb41bd6b
, 0x5be0cd19137e2179
]
-- | The initial value to start the blake2b hashing. This is equal to
-- the iv `xor` the parameter block.
sha256Init :: Sha256
sha256Init = Sha2 $ unsafeFromList [ 0x6a09e667
, 0xbb67ae85
, 0x3c6ef372
, 0xa54ff53a
, 0x510e527f
, 0x9b05688c
, 0x1f83d9ab
, 0x5be0cd19
]
---------------------------------- Memory element for Sha512 -----------------------
-- | The memory used by sha512 implementations.
type Sha512Mem = HashMemory128 Sha512
-- | The memory used bha sha256 implementations.
type Sha256Mem = HashMemory64 Sha256
instance Initialisable Sha256Mem () where
initialise _ = initialise sha256Init
instance Initialisable Sha512Mem () where
initialise _ = initialise sha512Init
-- | The block compressor for sha256.
type Compressor256 n = AlignedBlockPtr n Sha256
-> BlockCount Sha256
-> Sha256Mem -> IO ()
-- | The block compressor for sha512
type Compressor512 n = AlignedBlockPtr n Sha512
-> BlockCount Sha512
-> Sha512Mem -> IO ()
-- | Takes a block processing function for sha256 and gives a last
-- bytes processor.
process256Last :: KnownNat n
=> Compressor256 n -- ^ block compressor
-> AlignedBlockPtr n Sha256
-> BYTES Int
-> Sha256Mem
-> IO ()
process256Last comp buf nbytes sha256mem = do
updateLength nbytes sha256mem
totalBytes <- fmap bigEndian <$> getLength sha256mem
let pad = padding256 nbytes totalBytes
blocks = atMost $ transferSize pad
in unsafeTransfer pad buf >> comp buf blocks sha256mem
-- | Takes a block processing function for sha512 and gives a last
-- bytes processor.
process512Last :: KnownNat n
=> Compressor512 n
-> AlignedBlockPtr n Sha512
-> BYTES Int
-> Sha512Mem
-> IO ()
process512Last comp buf nbytes sha512mem = do
updateLength128 nbytes sha512mem
uLen <- fmap bigEndian <$> getULength sha512mem
lLen <- fmap bigEndian <$> getLLength sha512mem
let pad = padding512 nbytes uLen lLen
blocks = atMost $ transferSize pad
in unsafeTransfer pad buf >> comp buf blocks sha512mem
-- | The padding for sha256 as a writer.
padding256 :: BYTES Int -- Data in buffer.
-> BYTES (BE Word64) -- Message length
-> WriteTo
padding256 bufSize msgLen =
glueWrites 0 boundary (padBit1 bufSize) lengthWrite
where boundary = blocksOf 1 (Proxy :: Proxy Sha256)
lengthWrite = write $ shiftL msgLen 3
-- | The padding for sha512 as a writer.
padding512 :: BYTES Int -- Data in buffer.
-> BYTES (BE Word64) -- Message length higher
-> BYTES (BE Word64) -- Message length lower
-> WriteTo
padding512 bufSize uLen lLen = glueWrites 0 boundary (padBit1 bufSize) lengthWrite
where boundary = blocksOf 1 (Proxy :: Proxy Sha512)
lengthWrite = write up `mappend` write lp
up = shiftL uLen 3 .|. shiftR lLen 61
lp = shiftL lLen 3
-- | Pad the message with a 1-bit.
padBit1 :: BYTES Int -- ^ message length
-> WriteTo
padBit1 sz = skip sz <> writeStorable (0x80 :: Word8)