(*Specialization of HMAC256_DRBG_generate_algorithm: no additional input*)
Definition FunGenerate RI (WS: DRBG_functions.DRBG_working_state) n: DRBG_functions.DRBG_generate_algorithm_result :=
           HMAC256_DRBG_functional_prog.HMAC256_DRBG_generate_algorithm RI
                                           WS
                                           n
                                           nil.

(* Specifications: *)
Lemma GenerateCorrect RI k v z n (Z: (z<=RI)%Z) (N:(0<n)%nat): match GenUpdate_original_Zlist (k,v) n with (blocks,(k',v')) => FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success (firstn ((32 * n)%nat) (FCF.Fold.flatten (rev blocks))) (v',k',(z+1)%Z) end.
Lemma Generate_Blist_ok RI k v z n (Z: (z<=RI)%Z) l kk vv zz (N:(0<n)%nat): FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success l (kk,vv, zz) -> exists y, GenUpdate_original_Blist (bytesToBits k, bytesToBits v) n = (map bytesToBits y,(bytesToBits vv, bytesToBits kk)) /\ zz=z+1 /\ l = firstn (32 * n) (flatten (rev y)).
Lemma Generate_Bvec_ok' RI (k: list byte) v z n (Z: (z<=RI)%Z) l kk vv zz (N:(0<n)%nat) (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat): FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success l (kk,vv, zz) -> match GenUpdate_original_Bvec (of_list_length _ KL, of_list_length _ VL) n with (blocks, kv) => zz=z+1 /\ bitsToBytes (@Vector.to_list _ 256 (fst kv)) = vv /\ bitsToBytes (@Vector.to_list _ 256 (snd kv)) = kk /\ l = firstn (32 * n) (bitsToBytes (flatten (rev (map (@Vector.to_list _ 256) blocks)))) end.
Lemma Generate_Bvec_ok RI k v z n (Z: (z<=RI)%Z) (N:(0<n)%nat) (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat): match GenUpdate_original_Bvec (of_list_length _ KL, of_list_length _ VL) n with (blocks, (kk,vv)) => FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success (firstn (32 * n) (bitsToBytes (flatten (rev (map (@Vector.to_list _ 256) blocks))))) (bitsToBytes (@Vector.to_list _ 256 vv), bitsToBytes (@Vector.to_list _ 256 kk), z+1) end.
Lemma Generate_ok' RI k v z n (Z: (z<=RI)%Z) l kk vv zz (N:(0<n)%nat) (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat): FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success l (kk,vv, zz) -> match GenUpdate_original_core (of_list_length _ KL, of_list_length _ VL) n with (blocks, kv) => zz=z+1 /\ bitsToBytes (@Vector.to_list _ 256 (fst kv)) = vv /\ bitsToBytes (@Vector.to_list _ 256 (snd kv)) = kk /\ l = firstn (32 * n) (bitsToBytes (flatten (map (@Vector.to_list _ 256) blocks))) end.
Lemma Generate_ok RI k v z n (Z: (z<=RI)%Z) (N:(0<n)%nat) (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat): match GenUpdate_original_core (of_list_length _ KL, of_list_length _ VL) n with (blocks, (kk,vv)) => FunGenerate RI (v, k, z) (Z.of_nat ((32 * n)%nat)) = generate_algorithm_success (firstn (32 * n) (bitsToBytes (flatten (map (@Vector.to_list _ 256) blocks)))) (bitsToBytes (@Vector.to_list _ 256 vv), bitsToBytes (@Vector.to_list _ 256 kk), z+1) end.
Lemma Bridge' s I n bytes F ss (M: mbedtls_generate s I n = Some(bytes, ss, F)): match I with HMAC256DRBGabs K V reseed_counter entropy_len prediction_resistance reseed_interval => reseed_counter <= reseed_interval -> prediction_resistance = false -> match F with HMAC256DRBGabs KK VV rc _ _ _ => s=ss /\ rc=reseed_counter+1 /\ FunGenerate reseed_interval (V,K,reseed_counter) n = DRBG_functions.generate_algorithm_success bytes ((VV,KK), rc) end end.
Lemma Bridge_ok' s I (n:nat) bytes F ss (M: mbedtls_generate s I (32 * Z.of_nat n) = Some(bytes, ss, F)) (N:(0 < n)%nat): match I with HMAC256DRBGabs k v reseed_counter entropy_len prediction_resistance reseed_interval => reseed_counter <= reseed_interval -> prediction_resistance = false -> forall (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat), match F with HMAC256DRBGabs KK VV rc _ _ _ => s=ss /\ rc=reseed_counter+1 /\ match GenUpdate_original_core (Blist.of_list_length _ KL, Blist.of_list_length _ VL) n with (blocks, kv) => bitsToBytes (@Vector.to_list _ 256 (fst kv)) = KK /\ bitsToBytes (@Vector.to_list _ 256 (snd kv)) = VV /\ bytes = firstn (32 * n) (bitsToBytes (Fold.flatten (map (@Vector.to_list _ 256) blocks))) end end end.
Lemma GenUpdate_original_core_length: forall n state l m (G: GenUpdate_original_core state n = (l,m)), Datatypes.length l = n%nat.
Lemma fold_vector_length: forall l m, fold_left (fun (acc : nat) (a : Vector.t bool 256) => (acc + Datatypes.length (Vector.to_list a))%nat) l m = (m + Datatypes.length l * 256)%nat.
Lemma mbedtls_generate_Bridge s I (n:nat) bytes F ss (M: mbedtls_generate s I (32 * Z.of_nat n) = Some(bytes, ss, F)) (N:(0 < n)%nat): match I with HMAC256DRBGabs k v reseed_counter entropy_len prediction_resistance reseed_interval => reseed_counter <= reseed_interval -> prediction_resistance = false -> forall (KL: Datatypes.length (bytesToBits k) = 256%nat) (VL:Datatypes.length (bytesToBits v) = 256%nat), match F with HMAC256DRBGabs KK VV rc _ _ _ => s=ss /\ rc=reseed_counter+1 /\ match GenUpdate_original_core (Blist.of_list_length _ KL, Blist.of_list_length _ VL) n with (blocks, kv) => bitsToBytes (@Vector.to_list _ 256 (fst kv)) = KK /\ bitsToBytes (@Vector.to_list _ 256 (snd kv)) = VV /\ bytes = (bitsToBytes (Fold.flatten (map (@Vector.to_list _ 256) blocks))) end end end.