--------------------------------------------------------------------------------
-- ** SHA1
--------------------------------------------------------------------------------
--
-- todo: same assumption as for software version.
--
--------------------------------------------------------------------------------

sha1 :: Integer -> HArr HWord8 -> Hardware (HArr HWord8)
sha1 blocks message =
  do let f :: HInt -> HWord32 -> HWord32 -> HWord32 -> HWord32
         f t b c d =
           (0  <= t && t <= 19) ?? ((b .&. c) .|. (complement b .&. d)) $
           (20 <= t && t <= 39) ?? (b `xor` c `xor` d) $
           (40 <= t && t <= 59) ?? ((b .&. c) .|. (b .&. d) .|. (c .&. d))
                                 $ (b `xor` c `xor` d)

     let k :: HInt -> HWord32
         k t =
           (0  <= t && t <= 19) ?? 0x5a827999 $
           (20 <= t && t <= 39) ?? 0x6ed9eba1 $
           (40 <= t && t <= 59) ?? 0x8f1bbcdc
                                 $ 0xca62c1d6

     let step :: HIrr HWord32 -> HInt -> HBlock -> Hardware ()
         step w t block@(ra, rb, rc, rd, re) =
           do (a, b, c, d, e) <- freeze_block block
              temp <- shareM $
                a `rotateL` (5 :: HWord32) + (f t b c d) + e + (w !! t) + (k t)
              setRef re (d)
              setRef rd (c)
              setRef rc (b `rotateL` (30 :: HWord32))
              setRef rb (a)
              setRef ra (temp)

     -- format the message according to SHA1.
     let b = value blocks
     p  <- sha1_pad    b message
     w  <- sha1_extend b p
     -- fetch the initial 160-bit block.
     ib <- init_block
     -- process the blocks of w.
     for (0) (b-1) (\(i :: HExp Integer) ->
       do -- copy the current block.
          cb <- copy_block ib
          -- iterate step over block.
          for (0) (79) $ \i -> step w i cb
          -- add new block to previous block.
          add_block ib cb)
     -- translate the final block into an array of octets.
     sha1_block ib

--------------------------------------------------------------------------------
sha1 :: Integer -> HArr HWord8 -> Hardware (HArr HWord8)
sha1 blocks message =
  do let f :: HInt -> HWord32 -> HWord32 -> HWord32 -> HWord32
         f t b c d =
           (0  <= t && t <= 19) ?? ((b .&. c) .|. (complement b .&. d)) $
           (20 <= t && t <= 39) ?? (b `xor` c `xor` d) $
           (40 <= t && t <= 59) ?? ((b .&. c) .|. (b .&. d) .|. (c .&. d))
                                 $ (b `xor` c `xor` d)

     let k :: HInt -> HWord32
         k t =
           (0  <= t && t <= 19) ?? 0x5a827999 $
           (20 <= t && t <= 39) ?? 0x6ed9eba1 $
           (40 <= t && t <= 59) ?? 0x8f1bbcdc
                                 $ 0xca62c1d6

     let step :: HIrr HWord32 -> HInt -> HBlock -> Hardware ()
         step w t block@(ra, rb, rc, rd, re) =
           do (a, b, c, d, e) <- freeze_block block
              temp <- shareM $
                a `rotateL` (5 :: HWord32) + (f t b c d) + e + (w !! t) + (k t)
              setRef re (d)
              setRef rd (c)
              setRef rc (b `rotateL` (30 :: HWord32))
              setRef rb (a)
              setRef ra (temp)

     -- format the message according to SHA1.
     let b = value blocks
     p  <- sha1_pad    b message
     w  <- sha1_extend b p
     -- fetch the initial 160-bit block.
     ib <- init_block
     -- process the blocks of w.
     for (0) (b-1) (\(i :: HExp Integer) ->
       do -- copy the current block.
          cb <- copy_block ib
          -- iterate step over block.
          for (0) (79) $ \i -> step w i cb
          -- add new block to previous block.
          add_block ib cb)
     -- translate the final block into an array of octets.
     sha1_block ib

--------------------------------------------------------------------------------
sha1 blocks message =
  do let f :: HInt -> HWord32 -> HWord32 -> HWord32 -> HWord32
         f t b c d =
           (0  <= t && t <= 19) ?? ((b .&. c) .|. (complement b .&. d)) $
           (20 <= t && t <= 39) ?? (b `xor` c `xor` d) $
           (40 <= t && t <= 59) ?? ((b .&. c) .|. (b .&. d) .|. (c .&. d))
                                 $ (b `xor` c `xor` d)

     let k :: HInt -> HWord32
         k t =
           (0  <= t && t <= 19) ?? 0x5a827999 $
           (20 <= t && t <= 39) ?? 0x6ed9eba1 $
           (40 <= t && t <= 59) ?? 0x8f1bbcdc
                                 $ 0xca62c1d6

     let step :: HIrr HWord32 -> HInt -> HBlock -> Hardware ()
         step w t block@(ra, rb, rc, rd, re) =
           do (a, b, c, d, e) <- freeze_block block
              temp <- shareM $
                a `rotateL` (5 :: HWord32) + (f t b c d) + e + (w !! t) + (k t)
              setRef re (d)
              setRef rd (c)
              setRef rc (b `rotateL` (30 :: HWord32))
              setRef rb (a)
              setRef ra (temp)

     -- format the message according to SHA1.
     let b = value blocks
     p  <- sha1_pad    b message
     w  <- sha1_extend b p
     -- fetch the initial 160-bit block.
     ib <- init_block
     -- process the blocks of w.
     for (0) (b-1) (\(i :: HExp Integer) ->
       do -- copy the current block.
          cb <- copy_block ib
          -- iterate step over block.
          for (0) (79) $ \i -> step w i cb
          -- add new block to previous block.
          add_block ib cb)
     -- translate the final block into an array of octets.
     sha1_block ib

--------------------------------------------------------------------------------