val compute_w_post
      (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
      (n: nat)
      (res: Seq.lseq (word SHA1) n)
    : GTot Type0
let compute_w_post
  (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
  (n: nat)
  (res: Seq.lseq (word SHA1) n)
: GTot Type0
= (n <= 80 /\ (
    forall (i: nat) . i < n ==> Seq.index res i == w' mi i
  ))
val compute_w_post
      (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
      (n: nat)
      (res: Seq.lseq (word SHA1) n)
    : GTot Type0
let compute_w_post
      (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
      (n: nat)
      (res: Seq.lseq (word SHA1) n)
    : GTot Type0 =
(n <= 80 /\ (forall (i: nat). i < n ==> Seq.index res i == w' mi i))
Spec.SHA1.fst.checked
Spec.Loops.fst.checked Spec.Hash.Definitions.fst.checked prims.fst.checked Lib.IntTypes.fsti.checked FStar.UInt32.fsti.checked FStar.Seq.fst.checked FStar.Pervasives.fsti.checked FStar.List.Tot.fst.checked FStar.Classical.fsti.checked
Spec.SHA1.fst
FStar.Seq.Properties.lseq Spec.Hash.Definitions.word Spec.Hash.Definitions.SHA1 Spec.Hash.Definitions.block_word_length Prims.nat Prims.l_and Prims.b2t Prims.op_LessThanOrEqual Prims.l_Forall Prims.l_imp Prims.op_LessThan Prims.eq2 FStar.Seq.Base.index Spec.SHA1.w'
module Spec.SHA1

open Lib.IntTypes
module H = Spec.Hash.Definitions
module Seq = FStar.Seq

open Spec.Hash.Definitions
(* Source: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf *)

(* Section 5.3.1 *)

inline_for_extraction
let init_as_list : list uint32 = [
  u32 0x67452301;
  u32 0xefcdab89;
  u32 0x98badcfe;
  u32 0x10325476;
  u32 0xc3d2e1f0;
]

let init : words_state SHA1 = Seq.seq_of_list init_as_list

(* Section 6.1.2 Step 1: message schedule *)

let rec w' (mi: Seq.lseq (word SHA1) (block_word_length SHA1)) (t: nat {t <= 79}) : GTot (word SHA1) (decreases (t)) =
  if t < 16
  then Seq.index mi (t)
  else (w' mi (t - 3) ^. w' mi (t - 8) ^. w' mi (t - 14) ^. w' mi (t - 16)) <<<. 1ul

let w (mi: Seq.lseq (word SHA1) (block_word_length SHA1)) (t: size_t {v t <= 79}) : GTot (word SHA1) = w' mi (v t)

let compute_w_post
  (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
  (n: nat)
  (res: Seq.lseq (word SHA1) n)
val compute_w_post
      (mi: Seq.lseq (word SHA1) (block_word_length SHA1))
      (n: nat)
      (res: Seq.lseq (word SHA1) n)
    : GTot Type0

    mi:
      FStar.Seq.Properties.lseq (Spec.Hash.Definitions.word Spec.Hash.Definitions.SHA1)
        (Spec.Hash.Definitions.block_word_length Spec.Hash.Definitions.SHA1) ->
    n: Prims.nat ->
    res: FStar.Seq.Properties.lseq (Spec.Hash.Definitions.word Spec.Hash.Definitions.SHA1) n
  -> Prims.GTot Type0