Local Open Scope logic.
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Instance CompSpecs_Preserve: change_composite_env spec_sha.CompSpecs CompSpecs.
make_cs_preserve spec_sha.CompSpecs CompSpecs.
Defined.
Definition Vprog : varspecs.  mk_varspecs prog. Defined.
Record TREP := mkTrep { t: type; v: reptype t}.
Definition tp_of (T:TREP) : type.
destruct T. apply t0.
Defined.
Definition v_of (T:TREP) : reptype (tp_of T).
destruct T. apply v0.
Defined.
Definition memcpy_spec_data_at :=
DECLARE _memcpy
WITH rsh : share, wsh: share, p: val, q: val, T:TREP, n:Z
PRE [ 1%positive OF tptr tvoid, 2%positive OF tptr tvoid, 3%positive OF tuint ]
PROP (readable_share rsh; writable_share wsh;
n= sizeof (tp_of T); 0 <= n <= Int.max_unsigned)
LOCAL (temp 1%positive p; temp 2%positive q;
temp 3%positive (Vint (Int.repr n)))
SEP (data_at rsh (tp_of T) (v_of T) q;
memory_block wsh n p)
POST [ tptr tvoid ]
PROP ()
LOCAL (temp ret_temp p)
SEP (data_at wsh (tp_of T) (v_of T) p;
data_at rsh (tp_of T) (v_of T) q).
(****** Coq-representation of hmac states, and predicates characterizing the incremental functions.  If the corresponding predicates for SHA operations were modeled as functions, the ones here could be, too *)
Inductive hmacabs :=  (* HMAC abstract state *)
HMACabs: forall (ctx iSha oSha: s256abs) (*sha structures for md_ctx, i_ctx, o_ctx*),
hmacabs.
Definition absCtxt (h:hmacabs): s256abs :=
match h with HMACabs ctx _ _ => ctx end.
Definition innerShaInit (k: list byte):s256abs :=
HMAC_SHA256.mkArg k Ipad.
Definition outerShaInit (k: list byte):s256abs :=
HMAC_SHA256.mkArg k Opad.
Definition hmacInit (k:list byte):hmacabs :=
let key := HMAC_SHA256.mkKey k in
let iS := innerShaInit key in
let oS := outerShaInit key in
HMACabs iS iS oS.
Definition hmacUpdate (data: list byte) (h1:hmacabs): hmacabs :=
match h1 with
HMACabs ctx1 iS oS
=> let ctx2 := ctx1 ++ data in
HMACabs ctx2 iS oS
end.
Definition hmacFinalSimple h : list byte :=
match h with
HMACabs ctx iS oS
=> let inner := SHA256.SHA_256 ctx in
SHA256.SHA_256 (oS ++ inner)
end.
Definition hmacFinal h : (hmacabs * list byte) :=
match h with
HMACabs ctx iS oS
=> let inner := SHA256.SHA_256 ctx in
let outerArg := oS ++ inner in
(HMACabs outerArg iS oS, SHA256.SHA_256 outerArg)
end.
(*hmac cleanup not modelled*)
Definition hmacSimple (k:list byte) (data:list byte):list byte:=
hmacFinalSimple (hmacUpdate data (hmacInit k)).
Definition hmac (k:list byte) (data:list byte):(hmacabs * list byte) :=
hmacFinal (hmacUpdate data (hmacInit k)).

(* Specifications: *)
Lemma hmacSimple_sound k data:
hmacSimple k data = HMAC256 data k.
Lemma hmac_sound k data:
snd(hmac k data) = HMAC256 data k.
Lemma hmacUpdate_nil h: hmacUpdate [] h = h.
Definition HMAC_Cleanup_spec :=
DECLARE _HMAC_cleanup
WITH wsh: share, h: hmacabs, c : val
PRE [ _ctx OF tptr t_struct_hmac_ctx_st ]
PROP (writable_share wsh)
LOCAL (temp _ctx c)
SEP(hmacstate_PostFinal wsh h c)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP(data_block wsh (list_repeat (Z.to_nat(sizeof t_struct_hmac_ctx_st)) Byte.zero) c).