Require Recdef.
Require Coq.Strings.String.
Require Coq.Strings.Ascii.
(* LINEAR-TIME FUNCTIONAL VERSION OF SHA256 *)
Function zeros (n : Z) {measure Z.to_nat n} : list Int.int :=
if Z.gtb n 0 then Int.zero :: zeros (n-1) else nil.
Hint Rewrite length_zeros : norm.
Local Open Scope Z.
Definition padlen' (n: Z) : list Int.int :=
let q := (n+8)/64*16 + 15 - (n+8)/4   (* number of zero-pad words *)
in zeros q ++ [Int.repr (n * 8 / Int.modulus); Int.repr (n * 8)].
Transparent generate_word.
Definition nthB (b: list int) (i: nat) (n: Z) :=
nth (Z.to_nat (Z.of_nat i - 16 + n)) (rev (generate_word (rev b) 48)) Int.zero.
Opaque generate_word.
Definition c48 := 48%nat. Opaque c48.

Lemma process_msg_hash_blocks:
forall regs blocks,
(16 | Zlength blocks) ->
length regs = 8%nat ->
process_msg regs blocks = hash_blocks regs blocks.