unfold PRF_Advantage.
eapply ratDistance_eqRat_compat.
unfold PRF_G_A, HMAC, HMAC_spec.HMAC, GHMAC, NMAC_to_HMAC.GHMAC.
comp_skip.
unfold A_GHMAC.
eapply comp_spec_eq_impl_eq.
simpl.
inline_first.
comp_skip.
eapply (@oc_comp_spec_eq _ _ _ _ _ _ _ _ _ _ _ _ _  _ (fun a b => True)); intuition.
unfold f_oracle.
unfold HMAC_2K, HMAC_spec.GHMAC.
inline_first.
comp_simp.
inline_first.
comp_simp.
simpl.
eapply comp_spec_ret; intuition.
simpl in *.
comp_simp.
simpl.
inline_first.
comp_simp.
intuition; subst.
eapply comp_spec_eq_refl.
unfold PRF_G_B, A_GHMAC.
eapply comp_spec_eq_impl_eq.
simpl.
inline_first.
comp_skip.
eapply (@oc_comp_spec_eq _ _ _ _ _ _ _ _ _ _ _ _ _ _
(fun a b => forall x, arrayLookup _ (snd b) (splitAndPad x) = arrayLookup _ a x)).
intuition.
intuition.
inline_first.
unfold RndR_func, randomFunc.
rewrite H.
case_eq ( arrayLookup Message_EqDec x1 a ); intuition.
comp_simp.
inline_first.
comp_simp.
simpl.
eapply comp_spec_ret; intuition.
inline_first.
comp_skip.
comp_simp.
inline_first.
comp_simp.
simpl.
eapply comp_spec_ret; intuition.
simpl.
case_eq (eqb x a); intuition.
rewrite eqb_leibniz in H5.
subst.
rewrite eqb_refl.
trivial.
case_eq (eqb (splitAndPad x) (splitAndPad a)); intuition.
rewrite eqb_leibniz in H6.
apply splitAndPad_1_1 in H6.
subst.
rewrite eqb_refl in H5.
discriminate.
simpl in *.
intuition; subst.
comp_simp.
simpl.
inline_first.
comp_simp.
eapply comp_spec_eq_refl.
Qed.

(* Specifications: *)
Theorem HMAC_PRF:
PRF_Advantage (Rnd b) (Rnd c) HMAC _ _ A <=
RKA_Advantage _ _ _  ({ 0 , 1 }^b)
({ 0 , 1 }^c) (dual_f h) (BVxor b)
(HMAC_RKA_A h iv fpad opad ipad A_GHMAC) +
(PRF_Advantage ({ 0 , 1 }^c) ({ 0 , 1 }^c) h _ _
(PRF_h_A h_star_pad A_GHMAC) +
cAU.Adv_WCR _ _ h_star
({ 0 , 1 }^c) (Y (au_F_A A_GHMAC))).