Local Open Scope logic.
Definition Done (i:Z): int := Int.repr (digest_len*i).
Definition OUTpred PrkCont InfoCont sh z r cont p: mpred:=
data_at sh (tarray tuchar z) (sublist 0 z (map Vubyte (HKDF_expand PrkCont InfoCont cont))) p *
memory_block sh r (offset_val z p).
Definition PREVcont PRK INFO (i: Z): reptype (Tarray tuchar 32 noattr) :=
if zeq i 0 then list_repeat 32 Vundef
else (map Vubyte (Ti (CONT PRK) (CONT INFO) (Z.to_nat i))).

(* Specifications: *)
Lemma PREV_len PRK INFO i: 0 <= i -> Zlength (PREVcont PRK INFO i) = 32.
Lemma PREVcont_Sn PRK INFO i p: 0 <= i <= Byte.max_unsigned -> PREVcont PRK INFO i = map Vubyte p ->
PREVcont PRK INFO (i+1) = if zeq i 0 then map Vubyte (HMAC256_functional_prog.HMAC256 (CONT INFO ++ [Byte.one]) (CONT PRK))
else map Vubyte (HMAC256_functional_prog.HMAC256 (p ++ CONT INFO ++ [Byte.add (Byte.repr i) Byte.one]) (CONT PRK)).
Lemma PREV_listbyte PRK INFO i: 0 < i -> exists l, PREVcont PRK INFO i = map Vubyte l.
Lemma sublist_HKDF_expand4 PRK INFO i rest l (REST : 0 <= rest < 32)
(g : 255 >= i + 1) (OLEN : 32 * i + rest + 32 <= Int.max_unsigned)
(Hl : if zeq i 0 then l = [] else PREVcont PRK INFO i = map Vubyte l)
(Hi: 0 <= i):
sublist 0 rest
(HMAC256_functional_prog.HMAC256 ((l ++ CONT INFO) ++ [Byte.add (Byte.repr i) Byte.one]) (CONT PRK)) =
sublist (32 * i) (32 * i + rest) (HKDF_expand (CONT PRK) (CONT INFO) (32 * (i + 1))).
Lemma sublist_HKDF_expand5 PRK INFO l i
(Hl : if zeq i 0 then l = []
else PREVcont PRK INFO i = map Vubyte l)
(Hi : 0 <= i <= Byte.max_unsigned):
sublist 0 32 (HMAC256_functional_prog.HMAC256 ((l ++ CONT INFO) ++ [Byte.add (Byte.repr i) Byte.one]) (CONT PRK)) =
sublist (32 * i) (32 * i + 32) (HKDF_expand (CONT PRK) (CONT INFO) (32 * (i + 1))).
Lemma body_hkdf_expand: semax_body Hkdf_VarSpecs Hkdf_FunSpecs
f_HKDF_expand HKDF_expand_spec.