Local Open Scope logic.
Definition update_inner_if_then :=
(Ssequence
(Scall None
(Evar _memcpy
(Tfunction
(Tcons (tptr tvoid) (Tcons (tptr tvoid) (Tcons tuint Tnil)))
(tptr tvoid) cc_default))
[Ebinop Oadd (Etempvar _p (tptr tuchar)) (Etempvar _n tuint)
(tptr tuchar); Etempvar _data (tptr tuchar);
Etempvar _fragment tuint])
(Ssequence
(Scall None
(Evar _sha256_block_data_order
(Tfunction
(Tcons (tptr t_struct_SHA256state_st)
(Tcons (tptr tvoid) Tnil)) tvoid cc_default))
[Etempvar _c (tptr t_struct_SHA256state_st);
Etempvar _p (tptr tuchar)])
(Ssequence
(Sset _data
(Ebinop Oadd (Etempvar _data (tptr tuchar))
(Etempvar _fragment tuint) (tptr tuchar)))
(Ssequence
(Sset _len
(Ebinop Osub (Etempvar _len tuint)
(Etempvar _fragment tuint) tuint))
(Scall None
(Evar _memset
(Tfunction
(Tcons (tptr tvoid) (Tcons tint (Tcons tuint Tnil)))
(tptr tvoid) cc_default))
[Etempvar _p (tptr tuchar); Econst_int (Int.repr 0) tint;
Ebinop Omul (Econst_int (Int.repr 16) tint)
(Econst_int (Int.repr 4) tint) tint]))))).
Definition  update_inner_if_else :=
(Ssequence
(Scall None
(Evar _memcpy (Tfunction
(Tcons (tptr tvoid)
(Tcons (tptr tvoid)
(Tcons tuint Tnil))) (tptr tvoid) cc_default))
((Ebinop Oadd (Etempvar _p (tptr tuchar))
(Etempvar _n tuint) (tptr tuchar)) ::
(Etempvar _data (tptr tuchar)) ::
(Etempvar _len tuint) :: nil))
(Ssequence
(Sassign
(Efield
(Ederef (Etempvar _c (tptr t_struct_SHA256state_st))
t_struct_SHA256state_st) _num tuint)
(Ebinop Oadd (Etempvar _n tuint)
(Ecast (Etempvar _len tuint) tuint) tuint))
(Sreturn None))).
Definition update_inner_if :=
Sifthenelse (Ebinop Oge (Etempvar _len tuint)
(Etempvar _fragment tuint) tint)
update_inner_if_then
update_inner_if_else.
Definition inv_at_inner_if wsh sh hashed len c d dd data gv :=
(PROP ()
(LOCAL
(temp _fragment (Vint (Int.repr (64- Zlength dd)));
temp _p (field_address t_struct_SHA256state_st [StructField _data] c);
temp _n (Vint (Int.repr (Zlength dd)));
temp _data d; temp _c c;
temp _len (Vint (Int.repr len));
gvars gv)
SEP  (data_at wsh t_struct_SHA256state_st
(map Vint (hash_blocks init_registers hashed),
(Vint (lo_part (bitlength hashed dd + len*8)),
(Vint (hi_part (bitlength hashed dd + len*8)),
(map Vubyte dd ++ list_repeat (Z.to_nat (CBLOCKz-Zlength dd)) Vundef,
Vint (Int.repr (Zlength dd))))))
c;
K_vector gv;
data_block sh data d))).
Definition sha_update_inv wsh sh hashed len c d (dd: list byte) (data: list byte) gv (done: bool)
: environ -> mpred :=
(*EX blocks:list int,*)  (* this line doesn't work; bug in Coq 8.4pl3 thru 8.4pl6?  *)
@exp (environ->mpred) _ _  (fun blocks:list int =>
PROP  ((len >= Zlength blocks*4 - Zlength dd)%Z;
(LBLOCKz | Zlength blocks);
intlist_to_bytelist blocks = dd ++ sublist 0  (Zlength blocks * 4 - Zlength dd) data;
if done then (len-(Zlength blocks*4 - Zlength dd) < CBLOCKz)%Z else True)
LOCAL  (temp _p (field_address t_struct_SHA256state_st [StructField _data]  c);
temp _data
(field_address0 (tarray tuchar (Zlength data))
[ArraySubsc (Zlength blocks * 4 - Zlength dd)] d);
temp _c c;
temp _len (Vint (Int.repr (len- (Zlength blocks*4 - Zlength dd))));
gvars gv)
SEP  (K_vector gv;
@data_at CompSpecs wsh t_struct_SHA256state_st
((map Vint (hash_blocks init_registers (hashed++blocks)),
(Vint (lo_part (bitlength hashed dd + len*8)),
(Vint (hi_part (bitlength hashed dd + len*8)),
(list_repeat (Z.to_nat CBLOCKz) Vundef, Vundef)))) : reptype t_struct_SHA256state_st)
c;
data_block sh data d)).

Lemma update_inner_if_update_abs:
forall (hashed : list int) (dd data : list byte) (len : Z)
(H3 : Zlength dd < CBLOCKz)
(H4 : (LBLOCKz | Zlength hashed))
(H2 : 0 <= len < 64 - Zlength dd)
(H7: len <= Zlength data),
update_abs (sublist 0 len data) (S256abs hashed dd)
(S256abs hashed (dd ++ sublist 0 len data)).