Module Type HMAC_ABSTRACT_SPEC.
(*"Ordinary" abstract states contain a key and some data*)
Inductive HABS := hABS: forall (key data:list byte), HABS.
(*The mpred REP (hABS k d) c expresses that pointer value c holds a ctx representing the situation where we have hmac-ed data a with key k, and are prepeared to accept additional data.*)
Parameter REP: share -> HABS -> val -> mpred.
(*We have two additional protocol states. FULL k c holds after we return from hmac-final (so we can't hmac-updeate more data into ctx). It's the precondition of calls to hmac_init with argument key==null, ie the case where we want to reuse the key k in the next round of hmac. *)
Parameter FULL: share -> list byte -> val -> mpred.
(*EMPTY c captures the situation where we either haven't provided any key yet, or want to use an old ctx, but reinitialize its key. It occurs explicitly in the precondition of init_call with argument key==Vptr b i*)
Parameter EMPTY: share -> val -> mpred.
(*We can turn a memory block of hmac_ctx size into an EMPTY abstract HMAC REP*)
Parameter mkEmpty: forall sh v, data_at_ sh t_struct_hmac_ctx_st v |-- EMPTY sh v.
(*The reverse operation enables dellocation of stack-allocated hmac contexts at the end of client functions*)
Parameter EmptyDissolve: forall sh v, EMPTY sh v |-- data_at_ sh t_struct_hmac_ctx_st v.
(* We can prematurely terminate sequences of hmac-update by simply declaring an updateable ctx FULL*)
Parameter REP_FULL: forall sh key data c, REP sh (hABS key data) c |-- FULL sh key c.
(*We can also "wipe" a ctx, ie forget/erase any key material from ctx*)
Parameter FULL_EMPTY: forall sh key c, FULL sh key c |-- EMPTY sh c.
Parameter EMPTY_isptr: forall sh c, EMPTY sh c |-- !!isptr c.
(****** Next, here are the new specs of openssl's API functions *************)
(* I have split the two cases for hmac_init. mbedtls separates these situations in its API: mbedtls_md_hmac_reset prepares to authenticate a new message with the same key; mbedtls_md_hmac_starts sets the key and prepares to authenticate a new message. *)
Definition hmac_reset_spec :=
DECLARE _HMAC_Init (*Naphat: you'll probably have DECLARE mbedtls_hmac_reset here, and the
body of your wrapper function is a call to hmac_init with key==null.*)
WITH c : val, sh: share, l:Z, key:list byte, gv: globals
PRE [ _ctx OF tptr t_struct_hmac_ctx_st,
_key OF tptr tuchar,
_len OF tint ]
PROP (writable_share sh)
LOCAL (temp _ctx c; temp _key nullval; temp _len (Vint (Int.repr l));
gvars gv)
SEP (FULL sh key c; K_vector gv)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (REP sh (hABS key nil) c; K_vector gv).
Definition hmac_starts_spec :=
DECLARE _HMAC_Init (*Naphat: you'll probably have DECLARE mbedtls_hmac_starts here, and the
body of your wrapper function is a call to hmac_init with the nonnull key*)
WITH c : val, sh: share, l:Z, key:list byte, b:block, i:ptrofs, shk: share, gv: globals
PRE [ _ctx OF tptr t_struct_hmac_ctx_st,
_key OF tptr tuchar,
_len OF tint ]
PROP (writable_share sh; readable_share shk; has_lengthK l key)
LOCAL (temp _ctx c; temp _key (Vptr b i); temp _len (Vint (Int.repr l));
gvars gv)
SEP (EMPTY sh c; data_block shk key (Vptr b i); K_vector gv)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (REP sh (hABS key nil) c; data_block shk key (Vptr b i); K_vector gv).
Definition hmac_update_spec :=
DECLARE _HMAC_Update
WITH key: list byte, c : val, shc: share, d:val, shd: share, data:list byte, data1:list byte, gv:globals
PRE [ _ctx OF tptr t_struct_hmac_ctx_st,
_data OF tptr tvoid,
_len OF tuint]
PROP (writable_share shc; readable_share shd;
0 <= Zlength data1 <= Int.max_unsigned /\
Zlength data1 + Zlength data + 64 < two_power_pos 61)
LOCAL (temp _ctx c; temp _data d; temp  _len (Vint (Int.repr (Zlength data1)));
gvars gv)
SEP(REP shc (hABS key data) c; data_block shd data1 d; K_vector gv)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP(REP shc (hABS key (data++data1)) c;
data_block shd data1 d; K_vector gv).
Definition hmac_final_spec :=
DECLARE _HMAC_Final
WITH data:list byte, key:list byte, c : val, sh: share, md:val, shmd: share, gv:globals
PRE [ _ctx OF tptr t_struct_hmac_ctx_st,
_md OF tptr tuchar ]
PROP (writable_share sh; writable_share shmd)
LOCAL (temp _md md; temp _ctx c;
gvars gv)
SEP(REP sh (hABS key data) c; K_vector gv;
memory_block shmd 32 md)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP(K_vector gv; FULL sh key c;
data_block shmd (HMAC256 data key) md).
(*Maybe this is not needed in mbedtls?*)
Definition hmac_cleanup_spec :=
DECLARE _HMAC_cleanup
WITH key: list byte, c : val, sh: share
PRE [ _ctx OF tptr t_struct_hmac_ctx_st ]
PROP (writable_share sh)
LOCAL (temp _ctx c)
SEP(FULL sh key c)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP(EMPTY sh c).
Definition hmac_crypto_spec :=
DECLARE _HMAC
WITH md: val, KEY:DATA, shk: share,
msg: val, MSG:DATA, shm: share,
shmd: share, b:block, i:ptrofs, gv: globals
PRE [ _key OF tptr tuchar,
_key_len OF tint,
_d OF tptr tuchar,
_n OF tint,
_md OF tptr tuchar ]
PROP (readable_share shk; readable_share shm; writable_share shmd;
has_lengthK (LEN KEY) (CONT KEY);
has_lengthD 512 (LEN MSG) (CONT MSG))
LOCAL (temp _md md; temp _key (Vptr b i);
temp _key_len (Vint (Int.repr (LEN KEY)));
temp _d msg; temp _n (Vint (Int.repr (LEN MSG)));
gvars gv)
SEP(data_block shk (CONT KEY) (Vptr b i);
data_block shm (CONT MSG) msg;
memory_block shmd 32 md;
K_vector gv)
POST [ tptr tuchar ]
EX digest:_,
PROP (digest= HMAC256 (CONT MSG) (CONT KEY) /\
ByteBitRelations.bytesToBits digest =
verif_hmac_crypto.bitspec KEY MSG /\
forall A Awf, CRYPTO A Awf)
LOCAL (temp ret_temp md)
SEP(K_vector gv;
data_block shmd digest md;
data_block shm (CONT MSG) msg; data_block shk (CONT KEY) (Vptr b i)).
(* Finally, we have proofs that the openssl implementations satisfy these specs*)
Parameter body_hmac_final: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC_Final hmac_final_spec.
Parameter body_hmac_update: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC_Update hmac_update_spec.
Parameter body_hmac_starts: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC_Init hmac_starts_spec.
Parameter body_hmac_reset: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC_Init hmac_reset_spec.
Parameter body_hmac_cleanup: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC_cleanup hmac_cleanup_spec.
Parameter body_hmac_crypto: semax_body HmacVarSpecs HmacFunSpecs
f_HMAC hmac_crypto_spec.
End HMAC_ABSTRACT_SPEC.

Lemma haslengthK_simple: forall l, 0 < l <= Int.max_signed -> l * 8 < two_p 64.