HypreSpectre.SLH
From HyPre Require Import
NonInterference.
From HypreSpectre Require Import Lang Leak.
From Coq Require Import Program.Basics Program.Equality.
From Equations Require Import Equations.
NonInterference.
From HypreSpectre Require Import Lang Leak.
From Coq Require Import Program.Basics Program.Equality.
From Equations Require Import Equations.
Modeling Speculative Load Hardening
We use a special variable "__spec", which we assume is not used in the program. This is okay, as we know that our counterexample does not use it.
Definition pathcond := Not (Var "__spec"%string).
Definition update_pathcond e := Assign ("__spec"%string) (Plus (Var "__spec"%string) (Not e)).
Equations? speculative_load_hardening sl : list stmt by wf (stmt_depth_list sl) :=
speculative_load_hardening nil := nil;
speculative_load_hardening ((Assign x e) :: l) := Assign x (e) :: (speculative_load_hardening l);
speculative_load_hardening ((Read x e) :: l) := Read x (Mult pathcond e) :: (speculative_load_hardening l);
speculative_load_hardening ((Write x e) :: l) := Write x (Mult pathcond e) :: (speculative_load_hardening l);
speculative_load_hardening ((If i t e) :: l) := If i (update_pathcond i :: (speculative_load_hardening t)) (update_pathcond (Not i) :: (speculative_load_hardening e)) :: (speculative_load_hardening l);
speculative_load_hardening ((While e s1 s2) :: l) := While e (update_pathcond e :: (speculative_load_hardening s1)) (update_pathcond (Not e) :: (speculative_load_hardening s2)) :: (speculative_load_hardening l);
speculative_load_hardening ((Skip) :: l) := Skip :: (speculative_load_hardening l);
speculative_load_hardening ((Fence) :: l) := Fence :: (speculative_load_hardening l).
Proof.
all: replace ((fix aux (sl : list stmt) : nat :=
match sl with
| nil => 0
| x :: xs => S (stmt_depth x + aux xs)
end)) with (stmt_depth_list).
2, 4, 6, 8, 10, 12: reflexivity.
all: lia.
Qed.
Open Scope program_scope.
Definition update_pathcond e := Assign ("__spec"%string) (Plus (Var "__spec"%string) (Not e)).
Equations? speculative_load_hardening sl : list stmt by wf (stmt_depth_list sl) :=
speculative_load_hardening nil := nil;
speculative_load_hardening ((Assign x e) :: l) := Assign x (e) :: (speculative_load_hardening l);
speculative_load_hardening ((Read x e) :: l) := Read x (Mult pathcond e) :: (speculative_load_hardening l);
speculative_load_hardening ((Write x e) :: l) := Write x (Mult pathcond e) :: (speculative_load_hardening l);
speculative_load_hardening ((If i t e) :: l) := If i (update_pathcond i :: (speculative_load_hardening t)) (update_pathcond (Not i) :: (speculative_load_hardening e)) :: (speculative_load_hardening l);
speculative_load_hardening ((While e s1 s2) :: l) := While e (update_pathcond e :: (speculative_load_hardening s1)) (update_pathcond (Not e) :: (speculative_load_hardening s2)) :: (speculative_load_hardening l);
speculative_load_hardening ((Skip) :: l) := Skip :: (speculative_load_hardening l);
speculative_load_hardening ((Fence) :: l) := Fence :: (speculative_load_hardening l).
Proof.
all: replace ((fix aux (sl : list stmt) : nat :=
match sl with
| nil => 0
| x :: xs => S (stmt_depth x + aux xs)
end)) with (stmt_depth_list).
2, 4, 6, 8, 10, 12: reflexivity.
all: lia.
Qed.
Open Scope program_scope.
Sample Program
The program performs the same memory access in both branches, but once within and once outside of the speculation window.
Definition p := (Read "x"%string (Lit (-1)%Z)) :: (If (Var "x"%string) (Read "y"%string (Lit 1%Z) :: Skip :: Skip :: Skip :: nil) (Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Skip :: Read "y"%string (Lit 1%Z) :: nil)) :: nil.
Definition i0 : heap := alist_add decZ (-1)%Z 0%Z nil.
Definition i1 : heap := alist_add decZ (-1)%Z 1%Z nil.
Definition iv := Vector.cons _ i0 1 (Vector.cons _ i1 0 (Vector.nil _)).
Definition t0 := multi_step spec_step_fun ((None, nil, i0, (speculative_load_hardening p)) :: nil) 26.
Definition t1 := multi_step spec_step_fun ((None, nil, i1, (speculative_load_hardening p)) :: nil) 24.
Definition tv := Vector.cons _ t0 1 (Vector.cons _ t1 0 (Vector.nil _)).
Lemma compute_t0 : apply_lf' (rem_None ∘ leak_lm') t0 = Termination :: ReadAddress 1 :: ReadAddress 0 :: ReadAddress (-1) :: nil.
Proof.
unfold t0, p. simp speculative_load_hardening.
cbn.
reflexivity.
Qed.
Lemma compute_t1 : apply_lf' (rem_None ∘ leak_lm') t1 = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof.
unfold t1, p. simp speculative_load_hardening.
cbn.
reflexivity.
Qed.
Lemma compute_s0: apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i0, p) 20) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma compute_s0': apply_lf' (rem_None ∘ leak_lm) (multi_step nonspec_step_fun (nil, i0, p) 19) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma prefix_s0 n: n < 21 -> PreSuffix.prefix (apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i0, p) n)) (Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil).
Proof.
intros.
do 21 try destruct n.
22: lia.
all: cbn.
all: repeat econstructor.
Qed.
Lemma compute_s1: apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i1, p) 7) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma compute_s1': apply_lf' (rem_None ∘ leak_lm) (multi_step nonspec_step_fun (nil, i1, p) 6) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma prefix_s1 n: n < 8 -> PreSuffix.prefix (apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i1, p) n)) (Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil).
Proof.
intros.
do 8 try destruct n.
9: lia.
all: cbn.
all: repeat econstructor.
Qed.
Lemma prefix_app_help {T} (a b c : list T):
PreSuffix.prefix a b -> PreSuffix.prefix (a ++ c) (b ++ c).
Proof.
induction 1.
- constructor.
- now apply PreStep.
Qed.
Lemma stut_term_0 n:
(apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil).
Proof.
enough ((apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil) /\ multi_step_hd nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n = (alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil)). easy.
induction n.
- cbn. split; reflexivity.
- split.
+ rewrite multi_step_S2.
rewrite apply_lf'_S.
destruct IHn as [IHn1 IHn2].
rewrite IHn1, IHn2.
cbn. reflexivity.
+ unfold multi_step_hd.
rewrite multi_step_S2.
destruct IHn as [IHn1 IHn2].
rewrite IHn2. cbn. reflexivity.
Qed.
Lemma stut_term_1 n:
(apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil).
Proof.
enough ((apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil) /\ multi_step_hd nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n = (alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil)). easy.
induction n.
- cbn. split; reflexivity.
- split.
+ rewrite multi_step_S2.
rewrite apply_lf'_S.
destruct IHn as [IHn1 IHn2].
rewrite IHn1, IHn2.
cbn. reflexivity.
+ unfold multi_step_hd.
rewrite multi_step_S2.
destruct IHn as [IHn1 IHn2].
rewrite IHn2. cbn. reflexivity.
Qed.
Lemma iter_term_prefix n1 n2:
n1 <= n2 ->
PreSuffix.prefix
(Nat.iter n1 (fun a : list observation => Termination :: a)
(Termination :: nil))
(Nat.iter n2 (fun a : list observation => Termination :: a)
(Termination :: nil)).
Proof.
intros.
assert (n1 < n2 \/ n1 = n2) as [H1 | H1] by lia.
- clear H.
induction n2.
+ lia.
+ assert (n1 < n2 \/ n1 = n2) as [H | H] by lia.
* simpl. apply PreStep. auto.
* simpl. apply PreStep. rewrite H. constructor.
- rewrite H1. constructor.
Qed.
Definition i1 : heap := alist_add decZ (-1)%Z 1%Z nil.
Definition iv := Vector.cons _ i0 1 (Vector.cons _ i1 0 (Vector.nil _)).
Definition t0 := multi_step spec_step_fun ((None, nil, i0, (speculative_load_hardening p)) :: nil) 26.
Definition t1 := multi_step spec_step_fun ((None, nil, i1, (speculative_load_hardening p)) :: nil) 24.
Definition tv := Vector.cons _ t0 1 (Vector.cons _ t1 0 (Vector.nil _)).
Lemma compute_t0 : apply_lf' (rem_None ∘ leak_lm') t0 = Termination :: ReadAddress 1 :: ReadAddress 0 :: ReadAddress (-1) :: nil.
Proof.
unfold t0, p. simp speculative_load_hardening.
cbn.
reflexivity.
Qed.
Lemma compute_t1 : apply_lf' (rem_None ∘ leak_lm') t1 = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof.
unfold t1, p. simp speculative_load_hardening.
cbn.
reflexivity.
Qed.
Lemma compute_s0: apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i0, p) 20) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma compute_s0': apply_lf' (rem_None ∘ leak_lm) (multi_step nonspec_step_fun (nil, i0, p) 19) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma prefix_s0 n: n < 21 -> PreSuffix.prefix (apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i0, p) n)) (Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil).
Proof.
intros.
do 21 try destruct n.
22: lia.
all: cbn.
all: repeat econstructor.
Qed.
Lemma compute_s1: apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i1, p) 7) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma compute_s1': apply_lf' (rem_None ∘ leak_lm) (multi_step nonspec_step_fun (nil, i1, p) 6) = Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil.
Proof. reflexivity. Qed.
Lemma prefix_s1 n: n < 8 -> PreSuffix.prefix (apply_lf' (rem_None ∘ leak_lm) (multi_nonspec (nil, i1, p) n)) (Termination :: ReadAddress 1 :: ReadAddress (-1) :: nil).
Proof.
intros.
do 8 try destruct n.
9: lia.
all: cbn.
all: repeat econstructor.
Qed.
Lemma prefix_app_help {T} (a b c : list T):
PreSuffix.prefix a b -> PreSuffix.prefix (a ++ c) (b ++ c).
Proof.
induction 1.
- constructor.
- now apply PreStep.
Qed.
Lemma stut_term_0 n:
(apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil).
Proof.
enough ((apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil) /\ multi_step_hd nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil) n = (alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 0%Z nil), i0, nil)). easy.
induction n.
- cbn. split; reflexivity.
- split.
+ rewrite multi_step_S2.
rewrite apply_lf'_S.
destruct IHn as [IHn1 IHn2].
rewrite IHn1, IHn2.
cbn. reflexivity.
+ unfold multi_step_hd.
rewrite multi_step_S2.
destruct IHn as [IHn1 IHn2].
rewrite IHn2. cbn. reflexivity.
Qed.
Lemma stut_term_1 n:
(apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil).
Proof.
enough ((apply_lf' (rem_None ∘ leak_lm)
(multi_step nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n)) = Nat.iter n (fun a => Termination :: a) (Termination :: nil) /\ multi_step_hd nonspec_step_fun
(alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil) n = (alist_add RelDec_string "y"%string 0%Z
(alist_add RelDec_string "x"%string 1%Z nil), i1, nil)). easy.
induction n.
- cbn. split; reflexivity.
- split.
+ rewrite multi_step_S2.
rewrite apply_lf'_S.
destruct IHn as [IHn1 IHn2].
rewrite IHn1, IHn2.
cbn. reflexivity.
+ unfold multi_step_hd.
rewrite multi_step_S2.
destruct IHn as [IHn1 IHn2].
rewrite IHn2. cbn. reflexivity.
Qed.
Lemma iter_term_prefix n1 n2:
n1 <= n2 ->
PreSuffix.prefix
(Nat.iter n1 (fun a : list observation => Termination :: a)
(Termination :: nil))
(Nat.iter n2 (fun a : list observation => Termination :: a)
(Termination :: nil)).
Proof.
intros.
assert (n1 < n2 \/ n1 = n2) as [H1 | H1] by lia.
- clear H.
induction n2.
+ lia.
+ assert (n1 < n2 \/ n1 = n2) as [H | H] by lia.
* simpl. apply PreStep. auto.
* simpl. apply PreStep. rewrite H. constructor.
- rewrite H1. constructor.
Qed.
Lemma Hsrc_safe:
(forall a, Vector.Forall2 (nonspec_trace p) iv a -> v2 (ll_pre (rem_None ∘ leak_lm)) a).
Proof.
intros.
repeat dependent destruction a.
rewrite Vec_Forall2_forall2 in H.
specialize (H (Fin.FS Fin.F1)) as H0.
specialize (H Fin.F1).
simpl in H, H0.
unfold v2, ll_pre.
unfold nonspec_trace in *.
simpl.
destruct (Nat.lt_ge_cases (| h |) 21), (Nat.lt_ge_cases (| h0 |) 8).
- apply prefix_s0 in H1. apply prefix_s1 in H2.
eapply prefix_order_destruct;
fold value in *; fold heap in *; rewrite H in H1; rewrite H0 in H2; eauto.
- assert (exists n, | h0 | = n + 8) as [n Hn]. exists (| h0 | - 8). lia.
rewrite Hn in *.
unfold multi_nonspec, multi_step' in H0.
rewrite Nat.add_succ_r in H0.
rewrite <- Nat.add_succ_comm in H0.
rewrite multi_step_app in H0.
left.
rewrite <- H0.
rewrite apply_lf'_app.
apply prefix_app_r.
rewrite compute_s1'.
rewrite <- H.
now apply prefix_s0.
- assert (exists n, | h | = n + 21) as [n Hn]. exists (| h | - 21). lia.
rewrite Hn in *.
unfold multi_nonspec, multi_step' in H.
rewrite Nat.add_succ_r in H.
rewrite <- Nat.add_succ_comm in H.
rewrite multi_step_app in H.
right.
rewrite <- H.
rewrite apply_lf'_app.
apply prefix_app_r.
rewrite compute_s0'.
rewrite <- H0.
now apply prefix_s1.
- assert (exists n, | h | = n + 21) as [n Hn]. exists (| h | - 21); lia.
assert (exists n0, | h0 | = n0 + 8) as [n0 Hn0]. exists (| h0 | - 8); lia.
rewrite Hn, Hn0 in *.
rewrite Nat.add_succ_r in H, H0.
unfold multi_nonspec, multi_step' in *.
rewrite <- Nat.add_succ_comm in H, H0.
rewrite multi_step_app in H, H0.
rewrite <- H, <- H0.
rewrite! apply_lf'_app.
rewrite compute_s1', compute_s0'.
rewrite stut_term_0, stut_term_1.
destruct (Nat.lt_ge_cases n n0).
+ left. apply prefix_app_help. apply iter_term_prefix. lia.
+ right. apply prefix_app_help. apply iter_term_prefix. assumption.
Qed.
(forall a, Vector.Forall2 (nonspec_trace p) iv a -> v2 (ll_pre (rem_None ∘ leak_lm)) a).
Proof.
intros.
repeat dependent destruction a.
rewrite Vec_Forall2_forall2 in H.
specialize (H (Fin.FS Fin.F1)) as H0.
specialize (H Fin.F1).
simpl in H, H0.
unfold v2, ll_pre.
unfold nonspec_trace in *.
simpl.
destruct (Nat.lt_ge_cases (| h |) 21), (Nat.lt_ge_cases (| h0 |) 8).
- apply prefix_s0 in H1. apply prefix_s1 in H2.
eapply prefix_order_destruct;
fold value in *; fold heap in *; rewrite H in H1; rewrite H0 in H2; eauto.
- assert (exists n, | h0 | = n + 8) as [n Hn]. exists (| h0 | - 8). lia.
rewrite Hn in *.
unfold multi_nonspec, multi_step' in H0.
rewrite Nat.add_succ_r in H0.
rewrite <- Nat.add_succ_comm in H0.
rewrite multi_step_app in H0.
left.
rewrite <- H0.
rewrite apply_lf'_app.
apply prefix_app_r.
rewrite compute_s1'.
rewrite <- H.
now apply prefix_s0.
- assert (exists n, | h | = n + 21) as [n Hn]. exists (| h | - 21). lia.
rewrite Hn in *.
unfold multi_nonspec, multi_step' in H.
rewrite Nat.add_succ_r in H.
rewrite <- Nat.add_succ_comm in H.
rewrite multi_step_app in H.
right.
rewrite <- H.
rewrite apply_lf'_app.
apply prefix_app_r.
rewrite compute_s0'.
rewrite <- H0.
now apply prefix_s1.
- assert (exists n, | h | = n + 21) as [n Hn]. exists (| h | - 21); lia.
assert (exists n0, | h0 | = n0 + 8) as [n0 Hn0]. exists (| h0 | - 8); lia.
rewrite Hn, Hn0 in *.
rewrite Nat.add_succ_r in H, H0.
unfold multi_nonspec, multi_step' in *.
rewrite <- Nat.add_succ_comm in H, H0.
rewrite multi_step_app in H, H0.
rewrite <- H, <- H0.
rewrite! apply_lf'_app.
rewrite compute_s1', compute_s0'.
rewrite stut_term_0, stut_term_1.
destruct (Nat.lt_ge_cases n n0).
+ left. apply prefix_app_help. apply iter_term_prefix. lia.
+ right. apply prefix_app_help. apply iter_term_prefix. assumption.
Qed.
Theorem SLH_not_preserve_lm:
~ (
forall (iv: Vector.t heap 2),
forall (p_src: list stmt),
(forall a, Vector.Forall2 (nonspec_trace p_src) iv a -> v2 (ll_pre (rem_None ∘ leak_lm)) a) ->
(forall α, Vector.Forall2 (spec_am_trace (speculative_load_hardening p_src)) iv α -> v2 (ll_pre (rem_None ∘ leak_lm')) α)
).
Proof.
intros H.
specialize (H iv p).
specialize (H Hsrc_safe tv).
assert (Vector.Forall2 (spec_am_trace (speculative_load_hardening p)) iv tv).
{ rewrite Vec_Forall2_forall2.
intros i. repeat dependent induction i; simpl.
+ unfold spec_am_trace, multi_spec_am, multi_step', t0. rewrite multi_step_len. reflexivity.
+ unfold spec_am_trace, multi_spec_am, multi_step', t1. rewrite multi_step_len. reflexivity.
}
specialize (H H0). clear H0.
unfold v2, ll_pre in H.
unfold tv in H. simpl in H. rewrite compute_t0, compute_t1 in H.
destruct H.
+ inversion H; subst. inversion H2; subst. inversion H3; subst. inversion H4.
+ inversion H; subst. inversion H2; subst. inversion H2; subst. inversion H4; subst. inversion H5; subst. inversion H6.
Qed.
~ (
forall (iv: Vector.t heap 2),
forall (p_src: list stmt),
(forall a, Vector.Forall2 (nonspec_trace p_src) iv a -> v2 (ll_pre (rem_None ∘ leak_lm)) a) ->
(forall α, Vector.Forall2 (spec_am_trace (speculative_load_hardening p_src)) iv α -> v2 (ll_pre (rem_None ∘ leak_lm')) α)
).
Proof.
intros H.
specialize (H iv p).
specialize (H Hsrc_safe tv).
assert (Vector.Forall2 (spec_am_trace (speculative_load_hardening p)) iv tv).
{ rewrite Vec_Forall2_forall2.
intros i. repeat dependent induction i; simpl.
+ unfold spec_am_trace, multi_spec_am, multi_step', t0. rewrite multi_step_len. reflexivity.
+ unfold spec_am_trace, multi_spec_am, multi_step', t1. rewrite multi_step_len. reflexivity.
}
specialize (H H0). clear H0.
unfold v2, ll_pre in H.
unfold tv in H. simpl in H. rewrite compute_t0, compute_t1 in H.
destruct H.
+ inversion H; subst. inversion H2; subst. inversion H3; subst. inversion H4.
+ inversion H; subst. inversion H2; subst. inversion H2; subst. inversion H4; subst. inversion H5; subst. inversion H6.
Qed.
The proof relies on the following assumtions:
functional_extensionality_dep
: forall (A : Type) (B : A -> Type) (f g : forall x : A, B x),
(forall x : A, f x = g x) -> f = g
Eqdep.Eq_rect_eq.eq_rect_eq
: forall (U : Type) (p : U) (Q : U -> Type) (x : Q p) (h : p = p),
x = eq_rect p Q x p h