Parameter fpad_v : Bvector c -> Bvector p.
Parameter fpad : Blist -> Blist.
Parameter fpad_length: forall msg, length msg = c -> length (fpad msg) = p.
Parameter fpad_eq: forall v l, l = Vector.to_list v ->
fpad l = Vector.to_list (fpad_v v).
Parameter splitAndPad : Blist -> Blist.
Parameter splitAndPad_v : Blist -> list (Bvector b).
Parameter splitandpad_blocks: Blist -> list Blist.
Parameter sap_fpad: forall l m, length l = b ->
InBlocks 8 m ->
splitAndPad (l ++ m) = l ++ HMAC_Concat.app_fpad fpad m.
Parameter shasplitandpad_blocks_b:
forall m, Forall (fun x => length x = b) (splitandpad_blocks m).
Definition sap' (m:Blist):= concat (splitandpad_blocks m). (*plays role of sha_splitandpad_inc*)
Parameter sap_app : forall (l m : Blist),
length l = b ->
splitAndPad (l ++ m) = l ++ sap' m.
Parameter sap'_InBlocks: forall m, InBlocks b (sap' m).
Parameter hashblock : list int -> list int -> list int.
Parameter HHB : h =
(fun rgs bl : Blist =>
intsToBits (hashblock (bitsToInts rgs) (bitsToInts bl))).
Parameter hashblocks: list int -> list int -> list int.
Parameter d:nat.
Parameter HBS_eq : forall r msg : list int,
hashblocks r msg =
match msg with
| List.nil => r
| _ :: _ => hashblocks (hashblock r (firstn d msg)) (skipn d msg)
end.
Parameter D: (d * 32)%nat = b.
Parameter gap:list byte -> list int.
Parameter GAP: forall bits, NPeano.Nat.divide d (length (gap (bitsToBytes bits))).
Parameter sap_gap: splitAndPad = fun bits => bytesToBits (intlist_to_bytelist (gap (bitsToBytes bits))).
Parameter HASH: forall m, HF.Hash m = intlist_to_bytelist (hashblocks ir (gap m)).
Parameter FOLD_HB_eq: forall l ls, length l = (c + p)%nat ->
Forall (fun x => length x = (c + p)%nat) ls ->
fold_left h (l :: ls) (Vector.to_list iv_v) =
hash_blocks_bits (HMAC_spec_concat.HMAC_Concat.b c p) B h
(Vector.to_list iv_v) (l ++ concat ls).
Parameter length_splitandpad_inner: forall m,
Forall2
(fun (bv : Vector.t bool b) (bl : list bool) => bl = Vector.to_list bv)
(splitAndPad_v m) (splitandpad_blocks m).
End EQUIV_Inst.
Module HMAC_Equiv (HF:HP.HASH_FUNCTION) (EQ: EQUIV_Inst HF).
Module I<:INST.
Definition shah : Blist -> Blist ->  Blist := EQ.h.
Definition hashblock : list int -> list int -> list int :=EQ.hashblock.
Definition HHB : shah =
(fun rgs bl : Blist =>
intsToBits (hashblock (bitsToInts rgs) (bitsToInts bl))) := EQ.HHB.
Definition hashblocks: list int -> list int -> list int := EQ.hashblocks.
Definition d:nat := EQ.d.
Definition HBS_eq : forall r msg : list int,
hashblocks r msg =
match msg with
| List.nil => r
| _ :: _ => hashblocks (hashblock r (firstn d msg)) (skipn d msg)
end := EQ.HBS_eq.
End I.
(*Module HM:= HP.HMAC_FUN HF.*)
Module PAD := HMAC_Pad HF I.
Definition h_v (iv:Bvector EQ.c) (blk:Bvector EQ.b): Bvector EQ.c :=
of_list_length _
(EQ.h_length _ _ (VectorToList_length _ iv) (VectorToList_length _ blk)).

(* Specifications: *)
Lemma h_eq : forall (block_v : Bvector EQ.b) (block_l : Blist)
(HVL: block_l = Vector.to_list block_v)
ivA ivB (IV: ivA = Vector.to_list ivB),
EQ.h ivA block_l = Vector.to_list (h_v ivB block_v).