{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedNewtypes #-}
module Crypto.Hash.SHA256 (
hash
, Lazy.hash_lazy
, MAC(..)
, hmac
, Lazy.hmac_lazy
, _hmac_rr
, _hmac_rsb
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BI
import qualified Data.ByteString.Unsafe as BU
import Data.Word (Word8, Word32, Word64)
import Foreign.Ptr (Ptr)
import qualified GHC.Exts as Exts
import qualified Crypto.Hash.SHA256.Arm as Arm
import Crypto.Hash.SHA256.Internal
import qualified Crypto.Hash.SHA256.Lazy as Lazy
fi :: (Integral a, Num b) => a -> b
fi :: forall a b. (Integral a, Num b) => a -> b
fi = a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE fi #-}
hash :: BS.ByteString -> BS.ByteString
hash :: ByteString -> ByteString
hash ByteString
m
| Bool
Arm.sha256_arm_available = ByteString -> ByteString
Arm.hash ByteString
m
| Bool
otherwise = Registers -> ByteString
cat (Word64 -> Registers -> ByteString -> Registers
_hash Word64
0 (() -> Registers
iv ()) ByteString
m)
{-# INLINABLE hash #-}
_hash
:: Word64
-> Registers
-> BS.ByteString
-> Registers
_hash :: Word64 -> Registers -> ByteString -> Registers
_hash Word64
el Registers
rs m :: ByteString
m@(BI.PS ForeignPtr Word8
_ Int
_ Int
l) = do
let !state :: Registers
state = Registers -> ByteString -> Registers
_hash_blocks Registers
rs ByteString
m
!fin :: ByteString
fin@(BI.PS ForeignPtr Word8
_ Int
_ Int
ll) = Int -> ByteString -> ByteString
BU.unsafeDrop (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
64) ByteString
m
!total :: Word64
total = Word64
el Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Int
l
if Int
ll Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
56
then
let !ult :: Block
ult = ByteString -> Word64 -> Block
parse_pad1 ByteString
fin Word64
total
in Registers -> Block -> Registers
update Registers
state Block
ult
else
let !(# Block
pen, Block
ult #) = ByteString -> Word64 -> (# Block, Block #)
parse_pad2 ByteString
fin Word64
total
in Registers -> Block -> Registers
update (Registers -> Block -> Registers
update Registers
state Block
pen) Block
ult
{-# INLINABLE _hash #-}
_hash_blocks
:: Registers
-> BS.ByteString
-> Registers
_hash_blocks :: Registers -> ByteString -> Registers
_hash_blocks Registers
rs m :: ByteString
m@(BI.PS ForeignPtr Word8
_ Int
_ Int
l) = Registers -> Int -> Registers
loop Registers
rs Int
0 where
loop :: Registers -> Int -> Registers
loop !Registers
acc !Int
j
| Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
64 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
l = Registers
acc
| Bool
otherwise =
let !nacc :: Registers
nacc = Registers -> Block -> Registers
update Registers
acc (ByteString -> Int -> Block
parse ByteString
m Int
j)
in Registers -> Int -> Registers
loop Registers
nacc (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
64)
{-# INLINABLE _hash_blocks #-}
hmac :: BS.ByteString -> BS.ByteString -> MAC
hmac :: ByteString -> ByteString -> MAC
hmac ByteString
k ByteString
m
| Bool
Arm.sha256_arm_available = ByteString -> MAC
MAC (ByteString -> ByteString -> ByteString
Arm.hmac ByteString
k ByteString
m)
| Bool
otherwise = ByteString -> MAC
MAC (Registers -> ByteString
cat (Block -> ByteString -> Registers
_hmac (ByteString -> Block
prep_key ByteString
k) ByteString
m))
{-# INLINABLE hmac #-}
prep_key :: BS.ByteString -> Block
prep_key :: ByteString -> Block
prep_key k :: ByteString
k@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
64 = ByteString -> Block
parse_key (ByteString -> ByteString
hash ByteString
k)
| Bool
otherwise = ByteString -> Block
parse_key ByteString
k
{-# INLINABLE prep_key #-}
_hmac
:: Block
-> BS.ByteString
-> Registers
_hmac :: Block -> ByteString -> Registers
_hmac Block
k ByteString
m =
let !rs0 :: Registers
rs0 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
k (Word# -> Word32#
Exts.wordToWord32# Word#
0x36363636##))
!block :: Block
block = Registers -> Block
pad_registers_with_length (Word64 -> Registers -> ByteString -> Registers
_hash Word64
64 Registers
rs0 ByteString
m)
!rs1 :: Registers
rs1 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
k (Word# -> Word32#
Exts.wordToWord32# Word#
0x5C5C5C5C##))
in Registers -> Block -> Registers
update Registers
rs1 Block
block
{-# INLINABLE _hmac #-}
_hmac_rr
:: Ptr Word32
-> Ptr Word32
-> Registers
-> Registers
-> IO ()
_hmac_rr :: Ptr Word32 -> Ptr Word32 -> Registers -> Registers -> IO ()
_hmac_rr Ptr Word32
rp Ptr Word32
bp Registers
k Registers
m
| Bool
Arm.sha256_arm_available = Ptr Word32 -> Ptr Word32 -> Registers -> Registers -> IO ()
Arm._hmac_rr Ptr Word32
rp Ptr Word32
bp Registers
k Registers
m
| Bool
otherwise = do
let !key :: Block
key = Registers -> Block
pad_registers Registers
k
!block :: Block
block = Registers -> Block
pad_registers_with_length Registers
m
!rs :: Registers
rs = Block -> Block -> Registers
_hmac_bb Block
key Block
block
Ptr Word32 -> Registers -> IO ()
poke_registers Ptr Word32
rp Registers
rs
{-# INLINABLE _hmac_rr #-}
_hmac_bb
:: Block
-> Block
-> Registers
_hmac_bb :: Block -> Block -> Registers
_hmac_bb Block
k Block
m =
let !rs0 :: Registers
rs0 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
k (Word# -> Word32#
Exts.wordToWord32# Word#
0x36363636##))
!rs1 :: Registers
rs1 = Registers -> Block -> Registers
update Registers
rs0 Block
m
!inner :: Block
inner = Registers -> Block
pad_registers_with_length Registers
rs1
!rs2 :: Registers
rs2 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
k (Word# -> Word32#
Exts.wordToWord32# Word#
0x5C5C5C5C##))
in Registers -> Block -> Registers
update Registers
rs2 Block
inner
{-# INLINABLE _hmac_bb #-}
_hmac_rsb
:: Ptr Word32
-> Ptr Word32
-> Registers
-> Registers
-> Word8
-> BS.ByteString
-> IO ()
_hmac_rsb :: Ptr Word32
-> Ptr Word32
-> Registers
-> Registers
-> Word8
-> ByteString
-> IO ()
_hmac_rsb Ptr Word32
rp Ptr Word32
bp Registers
k Registers
v Word8
sep ByteString
dat
| Bool
Arm.sha256_arm_available = Ptr Word32
-> Ptr Word32
-> Registers
-> Registers
-> Word8
-> ByteString
-> IO ()
Arm._hmac_rsb Ptr Word32
rp Ptr Word32
bp Registers
k Registers
v Word8
sep ByteString
dat
| Bool
otherwise = do
let !key :: Block
key = Registers -> Block
pad_registers Registers
k
!rs0 :: Registers
rs0 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
key (Word# -> Word32#
Exts.wordToWord32# Word#
0x36363636##))
!inner :: Registers
inner = Word64
-> Registers -> Registers -> Word8 -> ByteString -> Registers
_hash_vsb Word64
64 Registers
rs0 Registers
v Word8
sep ByteString
dat
!block :: Block
block = Registers -> Block
pad_registers_with_length Registers
inner
!rs1 :: Registers
rs1 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word32# -> Block
xor Block
key (Word# -> Word32#
Exts.wordToWord32# Word#
0x5C5C5C5C##))
!rs :: Registers
rs = Registers -> Block -> Registers
update Registers
rs1 Block
block
Ptr Word32 -> Registers -> IO ()
poke_registers Ptr Word32
rp Registers
rs
{-# INLINABLE _hmac_rsb #-}
_hash_vsb
:: Word64
-> Registers
-> Registers
-> Word8
-> BS.ByteString
-> Registers
_hash_vsb :: Word64
-> Registers -> Registers -> Word8 -> ByteString -> Registers
_hash_vsb Word64
el Registers
rs0 Registers
v Word8
sep dat :: ByteString
dat@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
31 =
let !b0 :: Block
b0 = Registers -> Word8 -> ByteString -> Block
parse_vsb Registers
v Word8
sep ByteString
dat
!rs1 :: Registers
rs1 = Registers -> Block -> Registers
update Registers
rs0 Block
b0
!rest :: ByteString
rest = Int -> ByteString -> ByteString
BU.unsafeDrop Int
31 ByteString
dat
!rlen :: Int
rlen = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
31
!rs2 :: Registers
rs2 = Registers -> ByteString -> Registers
_hash_blocks Registers
rs1 ByteString
rest
!flen :: Int
flen = Int
rlen Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
64
!fin :: ByteString
fin = Int -> ByteString -> ByteString
BU.unsafeDrop (Int
rlen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
flen) ByteString
rest
!total :: Word64
total = Word64
el Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
33 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Int
l
in if Int
flen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
56
then Registers -> Block -> Registers
update Registers
rs2 (ByteString -> Word64 -> Block
parse_pad1 ByteString
fin Word64
total)
else let !(# Block
pen, Block
ult #) = ByteString -> Word64 -> (# Block, Block #)
parse_pad2 ByteString
fin Word64
total
in Registers -> Block -> Registers
update (Registers -> Block -> Registers
update Registers
rs2 Block
pen) Block
ult
| Bool
otherwise =
let !total :: Word64
total = Word64
el Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
33 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Int
l
in if Int
33 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
56
then Registers -> Block -> Registers
update Registers
rs0 (Registers -> Word8 -> ByteString -> Word64 -> Block
parse_pad1_vsb Registers
v Word8
sep ByteString
dat Word64
total)
else let !(# Block
pen, Block
ult #) = Registers -> Word8 -> ByteString -> Word64 -> (# Block, Block #)
parse_pad2_vsb Registers
v Word8
sep ByteString
dat Word64
total
in Registers -> Block -> Registers
update (Registers -> Block -> Registers
update Registers
rs0 Block
pen) Block
ult
{-# INLINABLE _hash_vsb #-}