{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedNewtypes #-}
module Crypto.Hash.SHA512 (
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, Word64)
import Foreign.Ptr (Ptr)
import qualified GHC.Exts as Exts
import qualified Crypto.Hash.SHA512.Arm as Arm
import Crypto.Hash.SHA512.Internal
import qualified Crypto.Hash.SHA512.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.sha512_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
128) 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
112
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
128 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
128)
{-# INLINABLE _hash_blocks #-}
hmac :: BS.ByteString -> BS.ByteString -> MAC
hmac :: ByteString -> ByteString -> MAC
hmac ByteString
k ByteString
m
| Bool
Arm.sha512_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
128 = 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 -> Word64# -> Block
xor Block
k (Word# -> Word64#
Exts.wordToWord64# Word#
0x3636363636363636##))
!block :: Block
block = Registers -> Block
pad_registers_with_length (Word64 -> Registers -> ByteString -> Registers
_hash Word64
128 Registers
rs0 ByteString
m)
!rs1 :: Registers
rs1 = Registers -> Block -> Registers
update (() -> Registers
iv ()) (Block -> Word64# -> Block
xor Block
k (Word# -> Word64#
Exts.wordToWord64# Word#
0x5C5C5C5C5C5C5C5C##))
in Registers -> Block -> Registers
update Registers
rs1 Block
block
{-# INLINABLE _hmac #-}
_hmac_rr
:: Ptr Word64
-> Ptr Word64
-> Registers
-> Registers
-> IO ()
_hmac_rr :: Ptr Word64 -> Ptr Word64 -> Registers -> Registers -> IO ()
_hmac_rr Ptr Word64
rp Ptr Word64
bp Registers
k Registers
m
| Bool
Arm.sha512_arm_available = Ptr Word64 -> Ptr Word64 -> Registers -> Registers -> IO ()
Arm._hmac_rr Ptr Word64
rp Ptr Word64
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 Word64 -> Registers -> IO ()
poke_registers Ptr Word64
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 -> Word64# -> Block
xor Block
k (Word# -> Word64#
Exts.wordToWord64# Word#
0x3636363636363636##))
!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 -> Word64# -> Block
xor Block
k (Word# -> Word64#
Exts.wordToWord64# Word#
0x5C5C5C5C5C5C5C5C##))
in Registers -> Block -> Registers
update Registers
rs2 Block
inner
{-# INLINABLE _hmac_bb #-}
_hmac_rsb
:: Ptr Word64
-> Ptr Word64
-> Registers
-> Registers
-> Word8
-> BS.ByteString
-> IO ()
_hmac_rsb :: Ptr Word64
-> Ptr Word64
-> Registers
-> Registers
-> Word8
-> ByteString
-> IO ()
_hmac_rsb Ptr Word64
rp Ptr Word64
bp Registers
k Registers
v Word8
sep ByteString
dat
| Bool
Arm.sha512_arm_available = Ptr Word64
-> Ptr Word64
-> Registers
-> Registers
-> Word8
-> ByteString
-> IO ()
Arm._hmac_rsb Ptr Word64
rp Ptr Word64
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 -> Word64# -> Block
xor Block
key (Word# -> Word64#
Exts.wordToWord64# Word#
0x3636363636363636##))
!inner :: Registers
inner = Word64
-> Registers -> Registers -> Word8 -> ByteString -> Registers
_hash_vsb Word64
128 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 -> Word64# -> Block
xor Block
key (Word# -> Word64#
Exts.wordToWord64# Word#
0x5C5C5C5C5C5C5C5C##))
!rs :: Registers
rs = Registers -> Block -> Registers
update Registers
rs1 Block
block
Ptr Word64 -> Registers -> IO ()
poke_registers Ptr Word64
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
63 =
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
63 ByteString
dat
!rlen :: Int
rlen = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
63
!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
128
!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
65 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
112
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
65 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
65 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
112
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 #-}