Section NMAC_to_HMAC.
Variable c p : nat.
Definition b := @b c p.
Variable h : Bvector c -> Bvector b -> Bvector c.
Variable iv : Bvector c.
Variable fpad : Bvector c -> Bvector p.
Definition GHMAC_2K := GHMAC_2K h iv fpad.
Variable opad ipad : Bvector b.
Hypothesis opad_ne_ipad : opad <> ipad.
Definition GHMAC := GHMAC h iv fpad opad ipad.
Variable A : OracleComp (list (Bvector b)) (Bvector c) bool.
Definition app_fpad := @app_fpad c p fpad.
Definition h_star := h_star p h.
Definition GNMAC := GNMAC h fpad.
Definition A_NMAC :=
x <-$ {0, 1}^(c + c);
[b, _] <-$2 A _ _ (f_oracle GNMAC _ x) tt;
ret b.
Definition A_HMAC :=
x <-$ {0, 1}^b;
[b, _] <-$2 A _ _ (f_oracle GHMAC _ x) tt;
ret b.
intuition.
unfold GHMAC_2K, HMAC_spec.GHMAC_2K, GNMAC, HMAC_spec.GNMAC, b, HMAC_spec.b.
remember (splitVector (c + p) (c + p) k) as z.
destruct z.
rewrite splitVector_append.
unfold app_fpad, hash_words.
simpl.
trivial.
Qed.
Definition HMAC_RKA_A : OracleComp (Bvector b * Bvector c) (Bvector c) bool :=
k_Out <--$ OC_Query _ (opad, iv);
k_In <--$ OC_Query _ (ipad, iv);
[b, _] <--$2 $ A _ _ (f_oracle GNMAC _ (Vector.append k_Out k_In)) tt;
$ ret b.
Local Opaque evalDist.

Theorem A_HMAC_RKA_equiv :
Pr[A_HMAC] == Pr[RKA_G0 _ (Rnd b) (dual_f h) (BVxor b) HMAC_RKA_A].