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)).

(* Specifications: *)
Lemma data_block_data_field:
forall sh dd dd' c,
(Zlength dd = CBLOCKz)%Z ->
JMeq (map Vubyte dd) dd' ->
data_block sh dd (field_address t_struct_SHA256state_st [StructField _data] c) =
field_at sh t_struct_SHA256state_st [StructField _data] dd' c.
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)).
Lemma update_inner_if_sha256_state_:
forall (hashed : list int) (dd data : list byte) (c d : val) (wsh sh : share) (len : Z)
(H : 0 <= len <= Zlength data)
(H4 : (LBLOCKz | Zlength hashed))
(H0 : 0 < 64 - Zlength dd <= 64)
(H2 : len < 64 - Zlength dd),
field_at wsh t_struct_SHA256state_st [StructField _data]
(map Vubyte dd ++
sublist 0 len (map Vubyte data) ++
list_repeat (Z.to_nat (CBLOCKz - Zlength dd - len)) Vundef) c *
field_at sh (tarray tuchar (Zlength data)) [] (map Vubyte data) d *
field_at wsh t_struct_SHA256state_st [StructField _h]
(map Vint (hash_blocks init_registers hashed)) c *
field_at wsh t_struct_SHA256state_st [StructField _Nl]
(Vint (lo_part (bitlength hashed dd + len * 8))) c *
field_at wsh t_struct_SHA256state_st [StructField _Nh]
(Vint (hi_part (bitlength hashed dd + len * 8))) c *
field_at wsh t_struct_SHA256state_st [StructField _num]
(Vint (Int.repr (Zlength dd + len))) c
|-- sha256state_ wsh (S256abs hashed (dd ++ sublist 0 len data)) c *
data_at sh (tarray tuchar (Zlength data)) (map Vubyte data) d.
(* move to pure_lemmas or whatever *)
Lemma map_Vubyte_eq':
forall bl, map Vint (map Int.repr (map Byte.unsigned bl)) = map Vubyte bl.
Lemma update_inner_if_proof:
forall (Espec: OracleKind) (hashed: list int) (dd data: list byte)
(c d: val) (wsh sh: share) (len: Z) gv
(H: (0 <= len <= Zlength data)%Z)
(Hwsh: writable_share wsh)
(Hsh: readable_share sh)
(LEN64: (bitlength hashed dd  + len * 8 < two_p 64)%Z)
(H3 : (Zlength dd < CBLOCKz)%Z)
(H4 : (LBLOCKz | Zlength hashed))
(Hlen : (len <= Int.max_unsigned)%Z),
semax (func_tycontext f_SHA256_Update Vprog Gtot nil)
(inv_at_inner_if wsh sh hashed len c d dd data gv)
update_inner_if
(overridePost (sha_update_inv wsh sh hashed len c d dd data gv false)
(frame_ret_assert
(function_body_ret_assert tvoid
(EX  a' : s256abs,
PROP  (update_abs (sublist 0 len data) (S256abs hashed dd) a')
LOCAL ()
SEP  (K_vector gv;
sha256state_ wsh a' c; data_block sh data d)))
emp)).