Module Type INST.
Parameter shah : Blist -> Blist ->  Blist.
Parameter hashblock : list int -> list int -> list int.
Parameter HHB : shah =
(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
| [] => r
| _ :: _ => hashblocks (hashblock r (firstn d msg)) (skipn d msg)
end.
End INST.
Module HMAC_Pad (HF:HP.HASH_FUNCTION) (I:INST).
(*Module HMAC_Pad.Declare Module HF:HP.HASH_FUNCTION.*)
Module HM:= HP.HMAC_FUN HF.
(*Module PadConcrete (HF:HP.HASH_FUNCTION).*)
(*From hmac_common_lemmas TODO: Isolate*)
(*Lemma SF_ByteRepr x: isbyteZ x -> HM.sixtyfour x = map Byte.unsigned (HM.sixtyfour (Byte.repr x)). *)
(*From hmac_common_lemmas TODO: Isolate*)
(*Lemma length_SF {A} (a:A) :length (HM.sixtyfour a) = HF.BlockSize. (* Lemma isbyte_hmaccore ipad opad m k: Forall isbyteZ (HM.HmacCore (Byte.repr ipad) (Byte.repr opad) m k).  Lemma fold_equiv_blocks b (B:(0<b)%nat) (DB32: (I.d*32)%nat=b): forall (l : Blist) (acc : Blist) (L : list int) (ACC : list int), InBlocks b l -> InBlocks I.d L -> l = convert L -> acc = convert ACC -> hash_blocks_bits b B I.shah acc l = convert (I.hashblocks ACC L).  Lemma equiv_pad shaiv shasplitandpad c p (B: (0< b c p)%nat) (DB32: (I.d*32 =b c p)%nat) ir (IVIR: shaiv = convert ir) gap (GAP: forall bits, NPeano.Nat.divide I.d (length (gap (bitsToBytes bits)))) (sap_gap: forall bits, shasplitandpad bits = bytesToBits (intlist_to_bytelist (gap (bitsToBytes bits)))) HASH (HSH: forall (m:list byte), HASH m = intlist_to_bytelist (I.hashblocks ir (gap m))): forall (bits : Blist) (bytes : list byte), bytes_bits_lists bits bytes -> bytes_bits_lists (hash_words_padded c p B I.shah shaiv shasplitandpad bits) (HASH bytes).  Theorem HMAC_pad_concrete splitandpad c p (B: (0< b c p)%nat) (BS: (HF.BlockSize * 8)%nat = b c p) (DB32: (I.d*32 =b c p)%nat) ir (*ie initial_regs*) gap (*ie generate_and_pad*)
(GAP: forall bits, NPeano.Nat.divide I.d (length (gap (bitsToBytes bits))))
(sap_gap: forall bits, splitandpad bits = bytesToBits (intlist_to_bytelist (gap (bitsToBytes bits))))
(HSH: forall (m:list byte), HF.Hash m = intlist_to_bytelist (I.hashblocks ir (gap m)))
(K : list byte) (M H : list byte) (OP IP : byte)
(k m h : Blist) (op ip : Blist):
length K = HF.BlockSize ->
bytes_bits_lists k K ->
bytes_bits_lists m M ->
bytes_bits_lists op (HM.sixtyfour OP) ->
bytes_bits_lists ip (HM.sixtyfour IP) ->
HMAC c p B I.shah (convert ir) splitandpad op ip k m = h ->
HM.HmacCore IP OP M K = H ->
bytes_bits_lists h H.

(* Specifications: *)
Theorem HMAC_pad_concrete' splitandpad c p (B: (0< b c p)%nat) (BS: (HF.BlockSize * 8)%nat =b c p)
(DB32: (I.d*32 =b c p)%nat)
ir (*ie initial_regs*) gap (*ie generate_and_pad*)
(GAP: forall bits, NPeano.Nat.divide I.d (length (gap (bitsToBytes bits))))
(sap_gap: splitandpad = fun bits => bytesToBits (intlist_to_bytelist (gap (bitsToBytes bits))))
(HSH: forall (m:list byte), HF.Hash m = intlist_to_bytelist (I.hashblocks ir (gap m)))
(K : list byte) (M : list byte) (OP IP : byte)
(k m : Blist) (op ip : Blist):
length K = HF.BlockSize ->
bytes_bits_lists k K ->
bytes_bits_lists m M ->
bytes_bits_lists op (HM.sixtyfour OP) ->
bytes_bits_lists ip (HM.sixtyfour IP) ->
bytes_bits_lists
(HMAC c p B I.shah (convert ir) splitandpad op ip k m)
(HM.HmacCore IP OP M K).