Theory Stateful_Protocol_Model
section‹Stateful Protocol Model›
theory Stateful_Protocol_Model
imports Stateful_Protocol_Composition_and_Typing.Stateful_Compositionality
Transactions Term_Abstraction
begin
subsection ‹Locale Setup›
locale stateful_protocol_model =
fixes arity⇩f::"'fun ⇒ nat"
and arity⇩s::"'sets ⇒ nat"
and public⇩f::"'fun ⇒ bool"
and Ana⇩f::"'fun ⇒ ((('fun,'atom::finite,'sets,'lbl) prot_fun, nat) term list × nat list)"
and Γ⇩f::"'fun ⇒ 'atom option"
and label_witness1::"'lbl"
and label_witness2::"'lbl"
assumes Ana⇩f_assm1: "∀f. let (K, M) = Ana⇩f f in (∀k ∈ subterms⇩s⇩e⇩t (set K).
is_Fun k ⟶ (is_Fu (the_Fun k)) ∧ length (args k) = arity⇩f (the_Fu (the_Fun k)))"
and Ana⇩f_assm2: "∀f. let (K, M) = Ana⇩f f in ∀i ∈ fv⇩s⇩e⇩t (set K) ∪ set M. i < arity⇩f f"
and public⇩f_assm: "∀f. arity⇩f f > (0::nat) ⟶ public⇩f f"
and Γ⇩f_assm: "∀f. arity⇩f f = (0::nat) ⟶ Γ⇩f f ≠ None"
and label_witness_assm: "label_witness1 ≠ label_witness2"
begin
lemma Ana⇩f_assm1_alt:
assumes "Ana⇩f f = (K,M)" "k ∈ subterms⇩s⇩e⇩t (set K)"
shows "(∃x. k = Var x) ∨ (∃h T. k = Fun (Fu h) T ∧ length T = arity⇩f h)"
proof (cases k)
case (Fun g T)
let ?P = "λk. is_Fun k ⟶ is_Fu (the_Fun k) ∧ length (args k) = arity⇩f (the_Fu (the_Fun k))"
let ?Q = "λK M. ∀k ∈ subterms⇩s⇩e⇩t (set K). ?P k"
have "?Q (fst (Ana⇩f f)) (snd (Ana⇩f f))" using Ana⇩f_assm1 split_beta[of ?Q "Ana⇩f f"] by meson
hence "?Q K M" using assms(1) by simp
hence "?P k" using assms(2) by blast
thus ?thesis using Fun by (cases g) auto
qed simp
lemma Ana⇩f_assm2_alt:
assumes "Ana⇩f f = (K,M)" "i ∈ fv⇩s⇩e⇩t (set K) ∪ set M"
shows "i < arity⇩f f"
using Ana⇩f_assm2 assms by fastforce
subsection ‹Definitions›
fun arity where
"arity (Fu f) = arity⇩f f"
| "arity (Set s) = arity⇩s s"
| "arity (Val _) = 0"
| "arity (Abs _) = 0"
| "arity Pair = 2"
| "arity (Attack _) = 0"
| "arity OccursFact = 2"
| "arity OccursSec = 0"
| "arity (PubConst _ _) = 0"
fun public where
"public (Fu f) = public⇩f f"
| "public (Set s) = (arity⇩s s > 0)"
| "public (Val n) = False"
| "public (Abs _) = False"
| "public Pair = True"
| "public (Attack _) = False"
| "public OccursFact = True"
| "public OccursSec = False"
| "public (PubConst _ _) = True"
fun Ana where
"Ana (Fun (Fu f) T) = (
if arity⇩f f = length T ∧ arity⇩f f > 0
then let (K,M) = Ana⇩f f in (K ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M)
else ([], []))"
| "Ana _ = ([], [])"
definition Γ⇩v where
"Γ⇩v v ≡ (
if (∀t ∈ subterms (fst v).
case t of (TComp f T) ⇒ arity f > 0 ∧ arity f = length T | _ ⇒ True)
then fst v
else TAtom Bottom)"
fun Γ where
"Γ (Var v) = Γ⇩v v"
| "Γ (Fun f T) = (
if arity f = 0
then case f of
(Fu g) ⇒ TAtom (case Γ⇩f g of Some a ⇒ Atom a | None ⇒ Bottom)
| (Val _) ⇒ TAtom Value
| (Abs _) ⇒ TAtom AbsValue
| (Set _) ⇒ TAtom SetType
| (Attack _) ⇒ TAtom AttackType
| OccursSec ⇒ TAtom OccursSecType
| (PubConst a _) ⇒ TAtom a
| _ ⇒ TAtom Bottom
else TComp f (map Γ T))"
lemma Γ_consts_simps[simp]:
"arity⇩f g = 0 ⟹ Γ (Fun (Fu g) []::('fun,'atom,'sets,'lbl) prot_term)
= TAtom (case Γ⇩f g of Some a ⇒ Atom a | None ⇒ Bottom)"
"Γ (Fun (Val n) []::('fun,'atom,'sets,'lbl) prot_term) = TAtom Value"
"Γ (Fun (Abs b) []::('fun,'atom,'sets,'lbl) prot_term) = TAtom AbsValue"
"arity⇩s s = 0 ⟹ Γ (Fun (Set s) []::('fun,'atom,'sets,'lbl) prot_term) = TAtom SetType"
"Γ (Fun (Attack x) []::('fun,'atom,'sets,'lbl) prot_term) = TAtom AttackType"
"Γ (Fun OccursSec []::('fun,'atom,'sets,'lbl) prot_term) = TAtom OccursSecType"
"Γ (Fun (PubConst a t) []::('fun,'atom,'sets,'lbl) prot_term) = TAtom a"
by simp+
lemma Γ_Fu_simps[simp]:
"arity⇩f f ≠ 0 ⟹ Γ (Fun (Fu f) T) = TComp (Fu f) (map Γ T)" (is "?A1 ⟹ ?A2")
"arity⇩f f = 0 ⟹ Γ⇩f f = Some a ⟹ Γ (Fun (Fu f) T) = TAtom (Atom a)" (is "?B1 ⟹ ?B2 ⟹ ?B3")
"arity⇩f f = 0 ⟹ Γ⇩f f = None ⟹ Γ (Fun (Fu f) T) = TAtom Bottom" (is "?C1 ⟹ ?C2 ⟹ ?C3")
"Γ (Fun (Fu f) T) ≠ TAtom Value" (is ?D)
"Γ (Fun (Fu f) T) ≠ TAtom AttackType" (is ?E)
"Γ (Fun (Fu f) T) ≠ TAtom OccursSecType" (is ?F)
proof -
show "?A1 ⟹ ?A2" by simp
show "?B1 ⟹ ?B2 ⟹ ?B3" by simp
show "?C1 ⟹ ?C2 ⟹ ?C3" by simp
show ?D by (cases "Γ⇩f f") simp_all
show ?E by (cases "Γ⇩f f") simp_all
show ?F by (cases "Γ⇩f f") simp_all
qed
lemma Γ_Set_simps[simp]:
"arity⇩s s ≠ 0 ⟹ Γ (Fun (Set s) T) = TComp (Set s) (map Γ T)"
"Γ (Fun (Set s) T) = TAtom SetType ∨ Γ (Fun (Set s) T) = TComp (Set s) (map Γ T)"
"Γ (Fun (Set s) T) ≠ TAtom Value"
"Γ (Fun (Set s) T) ≠ TAtom (Atom a)"
"Γ (Fun (Set s) T) ≠ TAtom AttackType"
"Γ (Fun (Set s) T) ≠ TAtom OccursSecType"
"Γ (Fun (Set s) T) ≠ TAtom Bottom"
by auto
subsection ‹Locale Interpretations›
lemma Ana_Fu_cases:
assumes "Ana (Fun f T) = (K,M)"
and "f = Fu g"
and "Ana⇩f g = (K',M')"
shows "(K,M) = (if arity⇩f g = length T ∧ arity⇩f g > 0
then (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M')
else ([],[]))" (is ?A)
and "(K,M) = (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M') ∨ (K,M) = ([],[])" (is ?B)
proof -
show ?A using assms by (cases "arity⇩f g = length T ∧ arity⇩f g > 0") auto
thus ?B by metis
qed
lemma Ana_Fu_intro:
assumes "arity⇩f f = length T" "arity⇩f f > 0"
and "Ana⇩f f = (K',M')"
shows "Ana (Fun (Fu f) T) = (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M')"
using assms by simp
lemma Ana_Fu_elim:
assumes "Ana (Fun f T) = (K,M)"
and "f = Fu g"
and "Ana⇩f g = (K',M')"
and "(K,M) ≠ ([],[])"
shows "arity⇩f g = length T" (is ?A)
and "(K,M) = (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M')" (is ?B)
proof -
show ?A using assms by force
moreover have "arity⇩f g > 0" using assms by force
ultimately show ?B using assms by auto
qed
lemma Ana_nonempty_inv:
assumes "Ana t ≠ ([],[])"
shows "∃f T. t = Fun (Fu f) T ∧ arity⇩f f = length T ∧ arity⇩f f > 0 ∧
(∃K M. Ana⇩f f = (K, M) ∧ Ana t = (K ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M))"
using assms
proof (induction t rule: Ana.induct)
case (1 f T)
hence *: "arity⇩f f = length T" "0 < arity⇩f f"
"Ana (Fun (Fu f) T) = (case Ana⇩f f of (K, M) ⇒ (K ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M))"
using Ana.simps(1)[of f T] unfolding Let_def by metis+
obtain K M where **: "Ana⇩f f = (K, M)" by (metis surj_pair)
hence "Ana (Fun (Fu f) T) = (K ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M)" using *(3) by simp
thus ?case using ** *(1,2) by blast
qed simp_all
lemma assm1:
assumes "Ana t = (K,M)"
shows "fv⇩s⇩e⇩t (set K) ⊆ fv t"
using assms
proof (induction t rule: term.induct)
case (Fun f T)
have aux: "fv⇩s⇩e⇩t (set K ⋅⇩s⇩e⇩t (!) T) ⊆ fv⇩s⇩e⇩t (set T)"
when K: "∀i ∈ fv⇩s⇩e⇩t (set K). i < length T"
for K::"(('fun,'atom,'sets,'lbl) prot_fun, nat) term list"
proof
fix x assume "x ∈ fv⇩s⇩e⇩t (set K ⋅⇩s⇩e⇩t (!) T)"
then obtain k where k: "k ∈ set K" "x ∈ fv (k ⋅ (!) T)" by moura
have "∀i ∈ fv k. i < length T" using K k(1) by simp
thus "x ∈ fv⇩s⇩e⇩t (set T)"
by (metis (no_types, lifting) k(2) contra_subsetD fv_set_mono image_subsetI nth_mem
subst_apply_fv_unfold)
qed
{ fix g assume f: "f = Fu g" and K: "K ≠ []"
obtain K' M' where *: "Ana⇩f g = (K',M')" by moura
have "(K, M) ≠ ([], [])" using K by simp
hence "(K, M) = (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M')" "arity⇩f g = length T"
using Ana_Fu_cases(1)[OF Fun.prems f *]
by presburger+
hence ?case using aux[of K'] Ana⇩f_assm2_alt[OF *] by auto
} thus ?case using Fun by (cases f) fastforce+
qed simp
lemma assm2:
assumes "Ana t = (K,M)"
and "⋀g S'. Fun g S' ⊑ t ⟹ length S' = arity g"
and "k ∈ set K"
and "Fun f T' ⊑ k"
shows "length T' = arity f"
using assms
proof (induction t rule: term.induct)
case (Fun g T)
obtain h where 2: "g = Fu h"
using Fun.prems(1,3) by (cases g) auto
obtain K' M' where 1: "Ana⇩f h = (K',M')" by moura
have "(K,M) ≠ ([],[])" using Fun.prems(3) by auto
hence "(K,M) = (K' ⋅⇩l⇩i⇩s⇩t (!) T, map ((!) T) M')"
"⋀i. i ∈ fv⇩s⇩e⇩t (set K') ∪ set M' ⟹ i < length T"
using Ana_Fu_cases(1)[OF Fun.prems(1) 2 1] Ana⇩f_assm2_alt[OF 1]
by presburger+
hence "K = K' ⋅⇩l⇩i⇩s⇩t (!) T" and 3: "∀i∈fv⇩s⇩e⇩t (set K'). i < length T" by simp_all
then obtain k' where k': "k' ∈ set K'" "k = k' ⋅ (!) T" using Fun.prems(3) by moura
hence 4: "Fun f T' ∈ subterms (k' ⋅ (!) T)" "fv k' ⊆ fv⇩s⇩e⇩t (set K')"
using Fun.prems(4) by auto
show ?case
proof (cases "∃i ∈ fv k'. Fun f T' ∈ subterms (T ! i)")
case True
hence "Fun f T' ∈ subterms⇩s⇩e⇩t (set T)" using k' Fun.prems(4) 3 by auto
thus ?thesis using Fun.prems(2) by auto
next
case False
then obtain S where "Fun f S ∈ subterms k'" "Fun f T' = Fun f S ⋅ (!) T"
using k'(2) Fun.prems(4) subterm_subst_not_img_subterm by force
thus ?thesis using Ana⇩f_assm1_alt[OF 1, of "Fun f S"] k'(1) by (cases f) auto
qed
qed simp
lemma assm4:
assumes "Ana (Fun f T) = (K, M)"
shows "set M ⊆ set T"
using assms
proof (cases f)
case (Fu g)
obtain K' M' where *: "Ana⇩f g = (K',M')" by moura
have "M = [] ∨ (arity⇩f g = length T ∧ M = map ((!) T) M')"
using Ana_Fu_cases(1)[OF assms Fu *]
by (meson prod.inject)
thus ?thesis using Ana⇩f_assm2_alt[OF *] by auto
qed auto
lemma assm5: "Ana t = (K,M) ⟹ K ≠ [] ∨ M ≠ [] ⟹ Ana (t ⋅ δ) = (K ⋅⇩l⇩i⇩s⇩t δ, M ⋅⇩l⇩i⇩s⇩t δ)"
proof (induction t rule: term.induct)
case (Fun f T) thus ?case
proof (cases f)
case (Fu g)
obtain K' M' where *: "Ana⇩f g = (K',M')" by moura
have **: "K = K' ⋅⇩l⇩i⇩s⇩t (!) T" "M = map ((!) T) M'"
"arity⇩f g = length T" "∀i ∈ fv⇩s⇩e⇩t (set K') ∪ set M'. i < arity⇩f g" "0 < arity⇩f g"
using Fun.prems(2) Ana_Fu_cases(1)[OF Fun.prems(1) Fu *] Ana⇩f_assm2_alt[OF *]
by (meson prod.inject)+
have ***: "∀i ∈ fv⇩s⇩e⇩t (set K'). i < length T" "∀i ∈ set M'. i < length T" using **(3,4) by auto
have "K ⋅⇩l⇩i⇩s⇩t δ = K' ⋅⇩l⇩i⇩s⇩t (!) (map (λt. t ⋅ δ) T)"
"M ⋅⇩l⇩i⇩s⇩t δ = map ((!) (map (λt. t ⋅ δ) T)) M'"
using subst_idx_map[OF ***(2), of δ]
subst_idx_map'[OF ***(1), of δ]
**(1,2)
by fast+
thus ?thesis using Fu * **(3,5) by auto
qed auto
qed simp
sublocale intruder_model arity public Ana
apply unfold_locales
by (metis assm1, metis assm2, rule Ana.simps, metis assm4, metis assm5)
adhoc_overloading INTRUDER_SYNTH intruder_synth
adhoc_overloading INTRUDER_DEDUCT intruder_deduct
lemma assm6: "arity c = 0 ⟹ ∃a. ∀X. Γ (Fun c X) = TAtom a" by (cases c) auto
lemma assm7: "0 < arity f ⟹ Γ (Fun f T) = TComp f (map Γ T)" by auto
lemma assm8: "infinite {c. Γ (Fun c []::('fun,'atom,'sets,'lbl) prot_term) = TAtom a ∧ public c}"
(is "?P a")
proof -
let ?T = "λf. (range f)::('fun,'atom,'sets,'lbl) prot_fun set"
let ?A = "λf. ∀x::nat ∈ UNIV. ∀y::nat ∈ UNIV. (f x = f y) = (x = y)"
let ?B = "λf. ∀x::nat ∈ UNIV. f x ∈ ?T f"
let ?C = "λf. ∀y::('fun,'atom,'sets,'lbl) prot_fun ∈ ?T f. ∃x ∈ UNIV. y = f x"
let ?D = "λf b. ?T f ⊆ {c. Γ (Fun c []::('fun,'atom,'sets,'lbl) prot_term) = TAtom b ∧ public c}"
have sub_lmm: "?P b" when "?A f" "?C f" "?C f" "?D f b" for b f
proof -
have "∃g::nat ⇒ ('fun,'atom,'sets,'lbl) prot_fun. bij_betw g UNIV (?T f)"
using bij_betwI'[of UNIV f "?T f"] that(1,2,3) by blast
hence "infinite (?T f)" by (metis nat_not_finite bij_betw_finite)
thus ?thesis using infinite_super[OF that(4)] by blast
qed
show ?thesis
proof (cases a)
case (Atom b) thus ?thesis using sub_lmm[of "PubConst (Atom b)" a] by force
next
case Value thus ?thesis using sub_lmm[of "PubConst Value" a] by force
next
case SetType thus ?thesis using sub_lmm[of "PubConst SetType" a] by fastforce
next
case AttackType thus ?thesis using sub_lmm[of "PubConst AttackType" a] by fastforce
next
case Bottom thus ?thesis using sub_lmm[of "PubConst Bottom" a] by fastforce
next
case OccursSecType thus ?thesis using sub_lmm[of "PubConst OccursSecType" a] by fastforce
next
case AbsValue thus ?thesis using sub_lmm[of "PubConst AbsValue" a] by force
qed
qed
lemma assm9: "TComp f T ⊑ Γ t ⟹ arity f > 0"
proof (induction t rule: term.induct)
case (Var x)
hence "Γ (Var x) ≠ TAtom Bottom" by force
hence "∀t ∈ subterms (fst x). case t of
TComp f T ⇒ arity f > 0 ∧ arity f = length T
| _ ⇒ True"
using Var Γ.simps(1)[of x] unfolding Γ⇩v_def by meson
thus ?case using Var by (fastforce simp add: Γ⇩v_def)
next
case (Fun g S)
have "arity g ≠ 0" using Fun.prems Var_subtermeq assm6 by force
thus ?case using Fun by (cases "TComp f T = TComp g (map Γ S)") auto
qed
lemma assm10: "wf⇩t⇩r⇩m (Γ (Var x))"
unfolding wf⇩t⇩r⇩m_def by (auto simp add: Γ⇩v_def)
lemma assm11: "arity f > 0 ⟹ public f" using public⇩f_assm by (cases f) auto
lemma assm12: "Γ (Var (τ, n)) = Γ (Var (τ, m))" by (simp add: Γ⇩v_def)
lemma assm13: "arity c = 0 ⟹ Ana (Fun c T) = ([],[])" by (cases c) simp_all
lemma assm14:
assumes "Ana (Fun f T) = (K,M)"
shows "Ana (Fun f T ⋅ δ) = (K ⋅⇩l⇩i⇩s⇩t δ, M ⋅⇩l⇩i⇩s⇩t δ)"
proof -
show ?thesis
proof (cases "(K, M) = ([],[])")
case True
{ fix g assume f: "f = Fu g"
obtain K' M' where "Ana⇩f g = (K',M')" by moura
hence ?thesis using assms f True by auto
} thus ?thesis using True assms by (cases f) auto
next
case False
then obtain g where **: "f = Fu g" using assms by (cases f) auto
obtain K' M' where *: "Ana⇩f g = (K',M')" by moura
have ***: "K = K' ⋅⇩l⇩i⇩s⇩t (!) T" "M = map ((!) T) M'" "arity⇩f g = length T"
"∀i ∈ fv⇩s⇩e⇩t (set K') ∪ set M'. i < arity⇩f g"
using Ana_Fu_cases(1)[OF assms ** *] False Ana⇩f_assm2_alt[OF *]
by (meson prod.inject)+
have ****: "∀i∈fv⇩s⇩e⇩t (set K'). i < length T" "∀i∈set M'. i < length T" using ***(3,4) by auto
have "K ⋅⇩l⇩i⇩s⇩t δ = K' ⋅⇩l⇩i⇩s⇩t (!) (map (λt. t ⋅ δ) T)"
"M ⋅⇩l⇩i⇩s⇩t δ = map ((!) (map (λt. t ⋅ δ) T)) M'"
using subst_idx_map[OF ****(2), of δ]
subst_idx_map'[OF ****(1), of δ]
***(1,2)
by auto
thus ?thesis using assms * ** ***(3) by auto
qed
qed
sublocale labeled_stateful_typing' arity public Ana Γ Pair label_witness1 label_witness2
apply unfold_locales
subgoal by (metis assm6)
subgoal by (metis assm7)
subgoal by (metis assm9)
subgoal by (rule assm10)
subgoal by (metis assm12)
subgoal by (metis assm13)
subgoal by (metis assm14)
subgoal by (rule label_witness_assm)
subgoal by (rule arity.simps(5))
subgoal by (metis assm14)
subgoal by (metis assm8)
subgoal by (metis assm11)
done
subsection ‹The Protocol Transition System, Defined in Terms of the Reachable Constraints›
definition transaction_decl_subst where
"transaction_decl_subst (ξ::('fun,'atom,'sets,'lbl) prot_subst) T ≡
subst_domain ξ = fst ` set (transaction_decl T ()) ∧
(∀(x,cs) ∈ set (transaction_decl T ()). ∃c ∈ cs.
ξ x = Fun (Fu c) [] ∧
arity (Fu c::('fun,'atom,'sets,'lbl) prot_fun) = 0) ∧
wt⇩s⇩u⇩b⇩s⇩t ξ"
definition transaction_fresh_subst where
"transaction_fresh_subst σ T 𝒜 ≡
subst_domain σ = set (transaction_fresh T) ∧
(∀t ∈ subst_range σ. ∃c. t = Fun c [] ∧ ¬public c ∧ arity c = 0) ∧
(∀t ∈ subst_range σ. t ∉ subterms⇩s⇩e⇩t (trms⇩l⇩s⇩s⇩t 𝒜)) ∧
(∀t ∈ subst_range σ. t ∉ subterms⇩s⇩e⇩t (trms_transaction T)) ∧
wt⇩s⇩u⇩b⇩s⇩t σ ∧ inj_on σ (subst_domain σ)"
definition transaction_renaming_subst where
"transaction_renaming_subst α P 𝒜 ≡
∃n ≥ max_var_set (⋃(vars_transaction ` set P) ∪ vars⇩l⇩s⇩s⇩t 𝒜). α = var_rename n"
definition (in intruder_model) constraint_model where
"constraint_model ℐ 𝒜 ≡
constr_sem_stateful ℐ (unlabel 𝒜) ∧
interpretation⇩s⇩u⇩b⇩s⇩t ℐ ∧
wf⇩t⇩r⇩m⇩s (subst_range ℐ)"
definition (in typed_model) welltyped_constraint_model where
"welltyped_constraint_model ℐ 𝒜 ≡ wt⇩s⇩u⇩b⇩s⇩t ℐ ∧ constraint_model ℐ 𝒜"
text ‹
The set of symbolic constraints reachable in any symbolic run of the protocol ‹P›.
‹ξ› instantiates the "declared variables" of transaction ‹T› with ground terms.
‹σ› instantiates the fresh variables of transaction ‹T› with fresh terms.
‹α› is a variable-renaming whose range consists of fresh variables.
›
inductive_set reachable_constraints::
"('fun,'atom,'sets,'lbl) prot ⇒ ('fun,'atom,'sets,'lbl) prot_constr set"
for P::"('fun,'atom,'sets,'lbl) prot"
where
init[simp]:
"[] ∈ reachable_constraints P"
| step:
"⟦𝒜 ∈ reachable_constraints P;
T ∈ set P;
transaction_decl_subst ξ T;
transaction_fresh_subst σ T 𝒜;
transaction_renaming_subst α P 𝒜
⟧ ⟹ 𝒜@dual⇩l⇩s⇩s⇩t (transaction_strand T ⋅⇩l⇩s⇩s⇩t ξ ∘⇩s σ ∘⇩s α) ∈ reachable_constraints P"
subsection ‹Minor Lemmata›
lemma Γ⇩v_TAtom[simp]: "Γ⇩v (TAtom a, n) = TAtom a"
unfolding Γ⇩v_def by simp
lemma Γ⇩v_TAtom':
assumes "a ≠ Bottom"
shows "Γ⇩v (τ, n) = TAtom a ⟷ τ = TAtom a"
proof
assume "Γ⇩v (τ, n) = TAtom a"
thus "τ = TAtom a" by (metis (no_types, lifting) assms Γ⇩v_def fst_conv term.inject(1))
qed simp
lemma Γ⇩v_TAtom_inv:
"Γ⇩v x = TAtom (Atom a) ⟹ ∃m. x = (TAtom (Atom a), m)"
"Γ⇩v x = TAtom Value ⟹ ∃m. x = (TAtom Value, m)"
"Γ⇩v x = TAtom SetType ⟹ ∃m. x = (TAtom SetType, m)"
"Γ⇩v x = TAtom AttackType ⟹ ∃m. x = (TAtom AttackType, m)"
"Γ⇩v x = TAtom OccursSecType ⟹ ∃m. x = (TAtom OccursSecType, m)"
by (metis Γ⇩v_TAtom' surj_pair prot_atom.distinct(7),
metis Γ⇩v_TAtom' surj_pair prot_atom.distinct(18),
metis Γ⇩v_TAtom' surj_pair prot_atom.distinct(26),
metis Γ⇩v_TAtom' surj_pair prot_atom.distinct(32),
metis Γ⇩v_TAtom' surj_pair prot_atom.distinct(38))
lemma Γ⇩v_TAtom'':
"(fst x = TAtom (Atom a)) = (Γ⇩v x = TAtom (Atom a))" (is "?A = ?A'")
"(fst x = TAtom Value) = (Γ⇩v x = TAtom Value)" (is "?B = ?B'")
"(fst x = TAtom SetType) = (Γ⇩v x = TAtom SetType)" (is "?C = ?C'")
"(fst x = TAtom AttackType) = (Γ⇩v x = TAtom AttackType)" (is "?D = ?D'")
"(fst x = TAtom OccursSecType) = (Γ⇩v x = TAtom OccursSecType)" (is "?E = ?E'")
proof -
have 1: "?A ⟹ ?A'" "?B ⟹ ?B'" "?C ⟹ ?C'" "?D ⟹ ?D'" "?E ⟹ ?E'"
by (metis Γ⇩v_TAtom prod.collapse)+
have 2: "?A' ⟹ ?A" "?B' ⟹ ?B" "?C' ⟹ ?C" "?D' ⟹ ?D" "?E' ⟹ ?E"
using Γ⇩v_TAtom Γ⇩v_TAtom_inv(1) apply fastforce
using Γ⇩v_TAtom Γ⇩v_TAtom_inv(2) apply fastforce
using Γ⇩v_TAtom Γ⇩v_TAtom_inv(3) apply fastforce
using Γ⇩v_TAtom Γ⇩v_TAtom_inv(4) apply fastforce
using Γ⇩v_TAtom Γ⇩v_TAtom_inv(5) by fastforce
show "?A = ?A'" "?B = ?B'" "?C = ?C'" "?D = ?D'" "?E = ?E'"
using 1 2 by metis+
qed
lemma Γ⇩v_Var_image:
"Γ⇩v ` X = Γ ` Var ` X"
by force
lemma Γ_Fu_const:
assumes "arity⇩f g = 0"
shows "∃a. Γ (Fun (Fu g) T) = TAtom (Atom a)"
proof -
have "Γ⇩f g ≠ None" using assms Γ⇩f_assm by blast
thus ?thesis using assms by force
qed
lemma Fun_Value_type_inv:
fixes T::"('fun,'atom,'sets,'lbl) prot_term list"
assumes "Γ (Fun f T) = TAtom Value"
shows "(∃n. f = Val n) ∨ (∃bs. f = Abs bs) ∨ (∃n. f = PubConst Value n)"
proof -
have *: "arity f = 0" by (metis const_type_inv assms)
show ?thesis using assms
proof (cases f)
case (Fu g)
hence "arity⇩f g = 0" using * by simp
hence False using Fu Γ_Fu_const[of g T] assms by auto
thus ?thesis by metis
next
case (Set s)
hence "arity⇩s s = 0" using * by simp
hence False using Set assms by auto
thus ?thesis by metis
qed simp_all
qed
lemma Ana⇩f_keys_not_val_terms:
assumes "Ana⇩f f = (K, T)"
and "k ∈ set K"
and "g ∈ funs_term k"
shows "¬is_Val g"
and "¬is_PubConstValue g"
and "¬is_Abs g"
proof -
{ assume "is_Val g"
then obtain n S where *: "Fun (Val n) S ∈ subterms⇩s⇩e⇩t (set K)"
using assms(2) funs_term_Fun_subterm[OF assms(3)]
by (cases g) auto
hence False using Ana⇩f_assm1_alt[OF assms(1) *] by simp
} moreover {
assume "is_PubConstValue g"
then obtain n S where *: "Fun (PubConst Value n) S ∈ subterms⇩s⇩e⇩t (set K)"
using assms(2) funs_term_Fun_subterm[OF assms(3)]
unfolding is_PubConstValue_def by (cases g) auto
hence False using Ana⇩f_assm1_alt[OF assms(1) *] by simp
} moreover {
assume "is_Abs g"
then obtain a S where *: "Fun (Abs a) S ∈ subterms⇩s⇩e⇩t (set K)"
using assms(2) funs_term_Fun_subterm[OF assms(3)]
by (cases g) auto
hence False using Ana⇩f_assm1_alt[OF assms(1) *] by simp
} ultimately show "¬is_Val g" "¬is_PubConstValue g" "¬is_Abs g" by metis+
qed
lemma Ana⇩f_keys_not_pairs:
assumes "Ana⇩f f = (K, T)"
and "k ∈ set K"
and "g ∈ funs_term k"
shows "g ≠ Pair"
proof
assume "g = Pair"
then obtain S where *: "Fun Pair S ∈ subterms⇩s⇩e⇩t (set K)"
using assms(2) funs_term_Fun_subterm[OF assms(3)]
by (cases g) auto
show False using Ana⇩f_assm1_alt[OF assms(1) *] by simp
qed
lemma Ana_Fu_keys_funs_term_subset:
fixes K::"('fun,'atom,'sets,'lbl) prot_term list"
assumes "Ana (Fun (Fu f) S) = (K, T)"
and "Ana⇩f f = (K', T')"
shows "⋃(funs_term ` set K) ⊆ ⋃(funs_term ` set K') ∪ funs_term (Fun (Fu f) S)"
proof -
{ fix k assume k: "k ∈ set K"
then obtain k' where k':
"k' ∈ set K'" "k = k' ⋅ (!) S" "arity⇩f f = length S"
"subterms k' ⊆ subterms⇩s⇩e⇩t (set K')"
using assms Ana_Fu_elim[OF assms(1) _ assms(2)] by fastforce
have 1: "funs_term k' ⊆ ⋃(funs_term ` set K')" using k'(1) by auto
have "i < length S" when "i ∈ fv k'" for i
using that Ana⇩f_assm2_alt[OF assms(2), of i] k'(1,3)
by auto
hence 2: "funs_term (S ! i) ⊆ funs_term (Fun (Fu f) S)" when "i ∈ fv k'" for i
using that by force
have "funs_term k ⊆ ⋃(funs_term ` set K') ∪ funs_term (Fun (Fu f) S)"
using funs_term_subst[of k' "(!) S"] k'(2) 1 2 by fast
} thus ?thesis by blast
qed
lemma Ana_Fu_keys_not_pubval_terms:
fixes k::"('fun,'atom,'sets,'lbl) prot_term"
assumes "Ana (Fun (Fu f) S) = (K, T)"
and "Ana⇩f f = (K', T')"
and "k ∈ set K"
and "∀g ∈ funs_term (Fun (Fu f) S). ¬is_PubConstValue g"
shows "∀g ∈ funs_term k. ¬is_PubConstValue g"
using assms(3,4) Ana⇩f_keys_not_val_terms(1,2)[OF assms(2)]
Ana_Fu_keys_funs_term_subset[OF assms(1,2)]
by blast
lemma Ana_Fu_keys_not_abs_terms:
fixes k::"('fun,'atom,'sets,'lbl) prot_term"
assumes "Ana (Fun (Fu f) S) = (K, T)"
and "Ana⇩f f = (K', T')"
and "k ∈ set K"
and "∀g ∈ funs_term (Fun (Fu f) S). ¬is_Abs g"
shows "∀g ∈ funs_term k. ¬is_Abs g"
using assms(3,4) Ana⇩f_keys_not_val_terms(3)[OF assms(2)]
Ana_Fu_keys_funs_term_subset[OF assms(1,2)]
by blast
lemma Ana_Fu_keys_not_pairs:
fixes k::"('fun,'atom,'sets,'lbl) prot_term"
assumes "Ana (Fun (Fu f) S) = (K, T)"
and "Ana⇩f f = (K', T')"
and "k ∈ set K"
and "∀g ∈ funs_term (Fun (Fu f) S). g ≠ Pair"
shows "∀g ∈ funs_term k. g ≠ Pair"
using assms(3,4) Ana⇩f_keys_not_pairs[OF assms(2)]
Ana_Fu_keys_funs_term_subset[OF assms(1,2)]
by blast
lemma Ana_Fu_keys_length_eq:
assumes "length T = length S"
shows "length (fst (Ana (Fun (Fu f) T))) = length (fst (Ana (Fun (Fu f) S)))"
proof (cases "arity⇩f f = length T ∧ arity⇩f f > 0")
case True thus ?thesis using assms by (cases "Ana⇩f f") auto
next
case False thus ?thesis using assms by force
qed
lemma deduct_occurs_in_ik:
fixes t::"('fun,'atom,'sets,'lbl) prot_term"
assumes t: "M ⊢ occurs t"
and M: "∀s ∈ subterms⇩s⇩e⇩t M. OccursFact ∉ ⋃(funs_term ` set (snd (Ana s)))"
"∀s ∈ subterms⇩s⇩e⇩t M. OccursSec ∉ ⋃(funs_term ` set (snd (Ana s)))"
"Fun OccursSec [] ∉ M"
shows "occurs t ∈ M"
using private_fun_deduct_in_ik''[of M OccursFact "[Fun OccursSec [], t]" OccursSec] t M
by fastforce
lemma constraint_model_prefix:
assumes "constraint_model I (A@B)"
shows "constraint_model I A"
by (metis assms strand_sem_append_stateful unlabel_append constraint_model_def)
lemma welltyped_constraint_model_prefix:
assumes "welltyped_constraint_model I (A@B)"
shows "welltyped_constraint_model I A"
by (metis assms constraint_model_prefix welltyped_constraint_model_def)
lemma welltyped_constraint_model_deduct_append:
assumes "welltyped_constraint_model I A"
and "ik⇩l⇩s⇩s⇩t A ⋅⇩s⇩e⇩t I ⊢ s ⋅ I"
shows "welltyped_constraint_model I (A@[(l,send⟨[s]⟩)])"
using assms strand_sem_append_stateful[of "{}" "{}" "unlabel A" _ I]
unfolding welltyped_constraint_model_def constraint_model_def by simp
lemma welltyped_constraint_model_deduct_split:
assumes "welltyped_constraint_model I (A@[(l,send⟨[s]⟩)])"
shows "welltyped_constraint_model I A"
and "ik⇩l⇩s⇩s⇩t A ⋅⇩s⇩e⇩t I ⊢ s ⋅ I"
using assms strand_sem_append_stateful[of "{}" "{}" "unlabel A" _ I]
unfolding welltyped_constraint_model_def constraint_model_def by simp_all
lemma welltyped_constraint_model_deduct_iff:
"welltyped_constraint_model I (A@[(l,send⟨[s]⟩)]) ⟷
welltyped_constraint_model I A ∧ ik⇩l⇩s⇩s⇩t A ⋅⇩s⇩e⇩t I ⊢ s ⋅ I"
by (metis welltyped_constraint_model_deduct_append welltyped_constraint_model_deduct_split)
lemma constraint_model_Val_is_Value_term:
assumes "welltyped_constraint_model I A"
and "t ⋅ I = Fun (Val n) []"
shows "t = Fun (Val n) [] ∨ (∃m. t = Var (TAtom Value, m))"
proof -
have "wt⇩s⇩u⇩b⇩s⇩t I" using assms(1) unfolding welltyped_constraint_model_def by simp
moreover have "Γ (Fun (Val n) []) = TAtom Value" by auto
ultimately have *: "Γ t = TAtom Value" by (metis (no_types) assms(2) wt_subst_trm'')
show ?thesis
proof (cases t)
case (Var x)
obtain τ m where x: "x = (τ, m)" by (metis surj_pair)
have "Γ⇩v x = TAtom Value" using * Var by auto
hence "τ = TAtom Value" using x Γ⇩v_TAtom'[of Value τ m] by simp
thus ?thesis using x Var by metis
next
case (Fun f T) thus ?thesis using assms(2) by auto
qed
qed
lemma wellformed_transaction_sem_receives:
fixes T::"('fun,'atom,'sets,'lbl) prot_transaction"
assumes T_valid: "wellformed_transaction T"
and ℐ: "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (transaction_strand T ⋅⇩l⇩s⇩s⇩t θ))) ℐ"
and s: "receive⟨ts⟩ ∈ set (unlabel (transaction_receive T ⋅⇩l⇩s⇩s⇩t θ))"
shows "∀t ∈ set ts. IK ⊢ t ⋅ ℐ"
proof -
let ?R = "unlabel (dual⇩l⇩s⇩s⇩t (transaction_receive T ⋅⇩l⇩s⇩s⇩t θ))"
let ?S = "λA. unlabel (dual⇩l⇩s⇩s⇩t (A ⋅⇩l⇩s⇩s⇩t θ))"
let ?S' = "?S (transaction_receive T)"
obtain l B s where B:
"(l,send⟨ts⟩) = dual⇩l⇩s⇩s⇩t⇩p ((l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ)"
"prefix ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ]) (transaction_receive T ⋅⇩l⇩s⇩s⇩t θ)"
using s dual⇩l⇩s⇩s⇩t_unlabel_steps_iff(2)[of ts "transaction_receive T ⋅⇩l⇩s⇩s⇩t θ"]
dual⇩l⇩s⇩s⇩t_in_set_prefix_obtain_subst[of "send⟨ts⟩" "transaction_receive T" θ]
by blast
have 1: "unlabel (dual⇩l⇩s⇩s⇩t ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ])) = unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[send⟨ts⟩]"
using B(1) unlabel_append dual⇩l⇩s⇩s⇩t⇩p_subst dual⇩l⇩s⇩s⇩t_subst singleton_lst_proj(4)
dual⇩l⇩s⇩s⇩t_subst_snoc subst_lsst_append subst_lsst_singleton
by (metis (no_types, lifting) subst_apply_labeled_stateful_strand_step.simps)
have "strand_sem_stateful IK DB ?S' ℐ"
using ℐ strand_sem_append_stateful[of IK DB _ _ ℐ] transaction_dual_subst_unfold[of T θ]
by fastforce
hence "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[send⟨ts⟩]) ℐ"
using B 1 unfolding prefix_def unlabel_def
by (metis dual⇩l⇩s⇩s⇩t_def map_append strand_sem_append_stateful)
hence t_deduct: "∀t ∈ set ts. IK ∪ (ik⇩l⇩s⇩s⇩t (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ)) ⋅⇩s⇩e⇩t ℐ) ⊢ t ⋅ ℐ"
using strand_sem_append_stateful[of IK DB "unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))" "[send⟨ts⟩]" ℐ]
by simp
have "∀s ∈ set (unlabel (transaction_receive T)). ∃t. s = receive⟨t⟩"
using T_valid wellformed_transaction_unlabel_cases(1)[OF T_valid] by auto
moreover { fix A::"('fun,'atom,'sets,'lbl) prot_strand" and θ
assume "∀s ∈ set (unlabel A). ∃t. s = receive⟨t⟩"
hence "∀s ∈ set (unlabel (A ⋅⇩l⇩s⇩s⇩t θ)). ∃t. s = receive⟨t⟩"
proof (induction A)
case (Cons a A) thus ?case using subst_lsst_cons[of a A θ] by (cases a) auto
qed simp
hence "∀s ∈ set (unlabel (A ⋅⇩l⇩s⇩s⇩t θ)). ∃t. s = receive⟨t⟩"
by (simp add: list.pred_set is_Receive_def)
hence "∀s ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (A ⋅⇩l⇩s⇩s⇩t θ))). ∃t. s = send⟨t⟩"
by (metis dual⇩l⇩s⇩s⇩t_memberD dual⇩l⇩s⇩s⇩t⇩p_inv(2) unlabel_in unlabel_mem_has_label)
}
ultimately have "∀s ∈ set ?R. ∃ts. s = send⟨ts⟩" by simp
hence "ik⇩s⇩s⇩t ?R = {}" unfolding unlabel_def ik⇩s⇩s⇩t_def by fast
hence "ik⇩l⇩s⇩s⇩t (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ)) = {}"
using B(2) 1 ik⇩s⇩s⇩t_append dual⇩l⇩s⇩s⇩t_append
by (metis (no_types, lifting) Un_empty map_append prefix_def unlabel_def)
thus ?thesis using t_deduct by simp
qed
lemma wellformed_transaction_sem_pos_checks:
assumes T_valid: "wellformed_transaction T"
and ℐ: "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (transaction_strand T ⋅⇩l⇩s⇩s⇩t θ))) ℐ"
and "⟨ac: t ∈ u⟩ ∈ set (unlabel (transaction_checks T ⋅⇩l⇩s⇩s⇩t θ))"
shows "(t ⋅ ℐ, u ⋅ ℐ) ∈ DB"
proof -
let ?s = "⟨ac: t ∈ u⟩"
let ?R = "transaction_receive T@transaction_checks T"
let ?R' = "unlabel (dual⇩l⇩s⇩s⇩t (?R ⋅⇩l⇩s⇩s⇩t θ))"
let ?S = "λA. unlabel (dual⇩l⇩s⇩s⇩t (A ⋅⇩l⇩s⇩s⇩t θ))"
let ?S' = "?S (transaction_receive T)@?S (transaction_checks T)"
let ?P = "λa. is_Receive a ∨ is_Check_or_Assignment a"
let ?Q = "λa. is_Send a ∨ is_Check_or_Assignment a"
have s: "?s ∈ set (unlabel (?R ⋅⇩l⇩s⇩s⇩t θ))"
using assms(3) subst_lsst_append[of "transaction_receive T"]
unlabel_append[of "transaction_receive T"]
by auto
obtain l B s where B:
"(l,?s) = dual⇩l⇩s⇩s⇩t⇩p ((l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ)"
"prefix ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ]) (?R ⋅⇩l⇩s⇩s⇩t θ)"
using s dual⇩l⇩s⇩s⇩t_unlabel_steps_iff(6)[of _ t u]
dual⇩l⇩s⇩s⇩t_in_set_prefix_obtain_subst[of ?s ?R θ]
by blast
have 1: "unlabel (dual⇩l⇩s⇩s⇩t ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ])) = unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[?s]"
using B(1) unlabel_append dual⇩l⇩s⇩s⇩t⇩p_subst dual⇩l⇩s⇩s⇩t_subst singleton_lst_proj(4)
dual⇩l⇩s⇩s⇩t_subst_snoc subst_lsst_append subst_lsst_singleton
by (metis (no_types, lifting) subst_apply_labeled_stateful_strand_step.simps )
have "strand_sem_stateful IK DB ?S' ℐ"
using ℐ strand_sem_append_stateful[of IK DB _ _ ℐ] transaction_dual_subst_unfold[of T θ]
by fastforce
hence "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[?s]) ℐ"
using B 1 strand_sem_append_stateful subst_lsst_append
unfolding prefix_def unlabel_def dual⇩l⇩s⇩s⇩t_def
by (metis (no_types) map_append)
hence in_db: "(t ⋅ ℐ, u ⋅ ℐ) ∈ dbupd⇩s⇩s⇩t (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))) ℐ DB"
using strand_sem_append_stateful[of IK DB "unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))" "[?s]" ℐ]
by simp
have "∀a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))). ?Q a"
proof
fix a assume a: "a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ)))"
have "?P a" when a: "a ∈ set (unlabel ?R)" for a
using a wellformed_transaction_unlabel_cases(1,2)[OF T_valid]
unfolding unlabel_def by fastforce
hence "?P a" when a: "a ∈ set (unlabel (?R ⋅⇩l⇩s⇩s⇩t θ))" for a
using a stateful_strand_step_cases_subst(2,11)[of _ θ] subst_lsst_unlabel[of ?R θ]
unfolding subst_apply_stateful_strand_def by auto
hence B_P: "∀a ∈ set (unlabel (B ⋅⇩l⇩s⇩s⇩t θ)). ?P a"
using unlabel_mono[OF set_mono_prefix[OF append_prefixD[OF B(2)]]]
by blast
obtain l where "(l,a) ∈ set (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))"
using a by (meson unlabel_mem_has_label)
then obtain b where b: "(l,b) ∈ set (B ⋅⇩l⇩s⇩s⇩t θ)" "dual⇩l⇩s⇩s⇩t⇩p (l,b) = (l,a)"
using dual⇩l⇩s⇩s⇩t_memberD by blast
hence "?P b" using B_P unfolding unlabel_def by fastforce
thus "?Q a" using dual⇩l⇩s⇩s⇩t⇩p_inv[OF b(2)] by (cases b) auto
qed
hence "∀a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))). ¬is_Insert a ∧ ¬is_Delete a" by fastforce
thus ?thesis using dbupd⇩s⇩s⇩t_no_upd[of "unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))" ℐ DB] in_db by simp
qed
lemma wellformed_transaction_sem_neg_checks:
assumes T_valid: "wellformed_transaction T"
and ℐ: "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (transaction_strand T ⋅⇩l⇩s⇩s⇩t θ))) ℐ"
and "NegChecks X [] [(t,u)] ∈ set (unlabel (transaction_checks T ⋅⇩l⇩s⇩s⇩t θ))"
shows "∀δ. subst_domain δ = set X ∧ ground (subst_range δ) ⟶ (t ⋅ δ ⋅ ℐ, u ⋅ δ ⋅ ℐ) ∉ DB" (is ?A)
and "X = [] ⟹ (t ⋅ ℐ, u ⋅ ℐ) ∉ DB" (is "?B ⟹ ?B'")
proof -
let ?s = "NegChecks X [] [(t,u)]"
let ?R = "transaction_receive T@transaction_checks T"
let ?R' = "unlabel (dual⇩l⇩s⇩s⇩t (?R ⋅⇩l⇩s⇩s⇩t θ))"
let ?S = "λA. unlabel (dual⇩l⇩s⇩s⇩t (A ⋅⇩l⇩s⇩s⇩t θ))"
let ?S' = "?S (transaction_receive T)@?S (transaction_checks T)"
let ?P = "λa. is_Receive a ∨ is_Check_or_Assignment a"
let ?Q = "λa. is_Send a ∨ is_Check_or_Assignment a"
let ?U = "λδ. subst_domain δ = set X ∧ ground (subst_range δ)"
have s: "?s ∈ set (unlabel (?R ⋅⇩l⇩s⇩s⇩t θ))"
using assms(3) subst_lsst_append[of "transaction_receive T"]
unlabel_append[of "transaction_receive T"]
by auto
obtain l B s where B:
"(l,?s) = dual⇩l⇩s⇩s⇩t⇩p ((l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ)"
"prefix ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ]) (?R ⋅⇩l⇩s⇩s⇩t θ)"
using s dual⇩l⇩s⇩s⇩t_unlabel_steps_iff(7)[of X "[]" "[(t,u)]"]
dual⇩l⇩s⇩s⇩t_in_set_prefix_obtain_subst[of ?s ?R θ]
by blast
have 1: "unlabel (dual⇩l⇩s⇩s⇩t ((B ⋅⇩l⇩s⇩s⇩t θ)@[(l,s) ⋅⇩l⇩s⇩s⇩t⇩p θ])) = unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[?s]"
using B(1) unlabel_append dual⇩l⇩s⇩s⇩t⇩p_subst dual⇩l⇩s⇩s⇩t_subst singleton_lst_proj(4)
dual⇩l⇩s⇩s⇩t_subst_snoc subst_lsst_append subst_lsst_singleton
by (metis (no_types, lifting) subst_apply_labeled_stateful_strand_step.simps)
have "strand_sem_stateful IK DB ?S' ℐ"
using ℐ strand_sem_append_stateful[of IK DB _ _ ℐ] transaction_dual_subst_unfold[of T θ]
by fastforce
hence "strand_sem_stateful IK DB (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))@[?s]) ℐ"
using B 1 strand_sem_append_stateful subst_lsst_append
unfolding prefix_def unlabel_def dual⇩l⇩s⇩s⇩t_def
by (metis (no_types) map_append)
hence "negchecks_model ℐ (dbupd⇩s⇩s⇩t (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))) ℐ DB) X [] [(t,u)]"
using strand_sem_append_stateful[of IK DB "unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))" "[?s]" ℐ]
by fastforce
hence in_db: "∀δ. ?U δ ⟶ (t ⋅ δ ⋅ ℐ, u ⋅ δ ⋅ ℐ) ∉ dbupd⇩s⇩s⇩t (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))) ℐ DB"
unfolding negchecks_model_def
by simp
have "∀a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))). ?Q a"
proof
fix a assume a: "a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ)))"
have "?P a" when a: "a ∈ set (unlabel ?R)" for a
using a wellformed_transaction_unlabel_cases(1,2,3)[OF T_valid]
unfolding unlabel_def by fastforce
hence "?P a" when a: "a ∈ set (unlabel (?R ⋅⇩l⇩s⇩s⇩t θ))" for a
using a stateful_strand_step_cases_subst(2,11)[of _ θ] subst_lsst_unlabel[of ?R θ]
unfolding subst_apply_stateful_strand_def by auto
hence B_P: "∀a ∈ set (unlabel (B ⋅⇩l⇩s⇩s⇩t θ)). ?P a"
using unlabel_mono[OF set_mono_prefix[OF append_prefixD[OF B(2)]]]
by blast
obtain l where "(l,a) ∈ set (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))"
using a by (meson unlabel_mem_has_label)
then obtain b where b: "(l,b) ∈ set (B ⋅⇩l⇩s⇩s⇩t θ)" "dual⇩l⇩s⇩s⇩t⇩p (l,b) = (l,a)"
using dual⇩l⇩s⇩s⇩t_memberD by blast
hence "?P b" using B_P unfolding unlabel_def by fastforce
thus "?Q a" using dual⇩l⇩s⇩s⇩t⇩p_inv[OF b(2)] by (cases b) auto
qed
hence "∀a ∈ set (unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))). ¬is_Insert a ∧ ¬is_Delete a" by fastforce
thus ?A using dbupd⇩s⇩s⇩t_no_upd[of "unlabel (dual⇩l⇩s⇩s⇩t (B ⋅⇩l⇩s⇩s⇩t θ))" ℐ DB] in_db by simp
moreover have "δ = Var" "t ⋅ δ = t"
when "subst_domain δ = set []" for t and δ::"('fun, 'atom, 'sets, 'lbl) prot_subst"
using that by auto
moreover have "subst_domain Var = set []" "range_vars Var = {}"
by simp_all
ultimately show "?B ⟹ ?B'" unfolding range_vars_alt_def by metis
qed
lemma dual_transaction_ik_is_transaction_send'':
fixes δ ℐ::"('a,'b,'c,'d) prot_subst"
assumes "wellformed_transaction T"
shows "(ik⇩s⇩s⇩t (unlabel (dual⇩l⇩s⇩s⇩t (transaction_strand T ⋅⇩l⇩s⇩s⇩t δ))) ⋅⇩s⇩e⇩t ℐ) ⋅⇩α⇩s⇩e⇩t a =
(trms⇩s⇩s⇩t (unlabel (transaction_send T)) ⋅⇩s⇩e⇩t δ ⋅⇩s⇩e⇩t ℐ) ⋅⇩α⇩s⇩e⇩t a" (is "?A = ?B")
using dual_transaction_ik_is_transaction_send[OF assms]
subst_lsst_unlabel[of "dual⇩l⇩s⇩s⇩t (transaction_strand T)" δ]
ik⇩s⇩s⇩t_subst[of "unlabel (dual⇩l⇩s⇩s⇩t (transaction_strand T))" δ]
dual⇩l⇩s⇩s⇩t_subst[of "transaction_strand T" δ]
by (auto simp add: abs_apply_terms_def)
lemma while_prot_terms_fun_mono:
"mono (λM'. M ∪ ⋃(subterms ` M') ∪ ⋃((set ∘ fst ∘ Ana) ` M'))"
unfolding mono_def by fast
lemma while_prot_terms_SMP_overapprox:
fixes M::"('fun,'atom,'sets,'lbl) prot_terms"
assumes N_supset: "M ∪ ⋃(subterms ` N) ∪ ⋃((set ∘ fst ∘ Ana) ` N) ⊆ N"
and Value_vars_only: "∀x ∈ fv⇩s⇩e⇩t N. Γ⇩v x = TAtom Value"
shows "SMP M ⊆ {a ⋅ δ | a δ. a ∈ N ∧ wt⇩s⇩u⇩b⇩s⇩t δ ∧ wf⇩t⇩r⇩m⇩s (subst_range δ)}"
proof -
define f where "f ≡ λM'. M ∪ ⋃(subterms ` M') ∪ ⋃((set ∘ fst ∘ Ana) ` M')"
define S where "S ≡ {a ⋅ δ | a δ. a ∈ N ∧ wt⇩s⇩u⇩b⇩s⇩t δ ∧ wf⇩t⇩r⇩m⇩s (subst_range δ)}"
note 0 = Value_vars_only
have "t ∈ S" when "t ∈ SMP M" for t
using that
proof (induction t rule: SMP.induct)
case (MP t)
hence "t ∈ N" "wt⇩s⇩u⇩b⇩s⇩t Var" "wf⇩t⇩r⇩m⇩s (subst_range Var)" using N_supset by auto
hence "t ⋅ Var ∈ S" unfolding S_def by blast
thus ?case by simp
next
case (Subterm t t')
then obtain δ a where a: "a ⋅ δ = t" "a ∈ N" "wt⇩s⇩u⇩b⇩s⇩t δ" "wf⇩t⇩r⇩m⇩s (subst_range δ)"
by (auto simp add: S_def)
hence "∀x ∈ fv a. ∃τ. Γ (Var x) = TAtom τ" using 0 by auto
hence *: "∀x ∈ fv a. (∃f. δ x = Fun f []) ∨ (∃y. δ x = Var y)"
using a(3) TAtom_term_cases[OF wf_trm_subst_rangeD[OF a(4)]]
by (metis wt⇩s⇩u⇩b⇩s⇩t_def)
obtain b where b: "b ⋅ δ = t'" "b ∈ subterms a"
using subterms_subst_subterm[OF *, of t'] Subterm.hyps(2) a(1)
by fast
hence "b ∈ N" using N_supset a(2) by blast
thus ?case using a b(1) unfolding S_def by blast
next
case (Substitution t θ)
then obtain δ a where a: "a ⋅ δ = t" "a ∈ N" "wt⇩s⇩u⇩b⇩s⇩t δ" "wf⇩t⇩r⇩m⇩s (subst_range δ)"
by (auto simp add: S_def)
have "wt⇩s⇩u⇩b⇩s⇩t (δ ∘⇩s θ)" "wf⇩t⇩r⇩m⇩s (subst_range (δ ∘⇩s θ))"
by (fact wt_subst_compose[OF a(3) Substitution.hyps(2)],
fact wf_trms_subst_compose[OF a(4) Substitution.hyps(3)])
moreover have "t ⋅ θ = a ⋅ δ ∘⇩s θ" using a(1) subst_subst_compose[of a δ θ] by simp
ultimately show ?case using a(2) unfolding S_def by blast
next
case (Ana t K T k)
then obtain δ a where a: "a ⋅ δ = t" "a ∈ N" "wt⇩s⇩u⇩b⇩s⇩t δ" "wf⇩t⇩r⇩m⇩s (subst_range δ)"
by (auto simp add: S_def)
obtain Ka Ta where a': "Ana a = (Ka,Ta)" by moura
have *: "K = Ka ⋅⇩l⇩i⇩s⇩t δ"
proof (cases a)
case (Var x)
then obtain g U where gU: "t = Fun g U"
using a(1) Ana.hyps(2,3) Ana_var
by (cases t) simp_all
have "Γ (Var x) = TAtom Value" using Var a(2) 0 by auto
hence "Γ (Fun g U) = TAtom Value"
using a(1,3) Var gU wt_subst_trm''[OF a(3), of a]
by argo
thus ?thesis using gU Fun_Value_type_inv Ana.hyps(2,3) by fastforce
next
case (Fun g U) thus ?thesis using a(1) a' Ana.hyps(2) Ana_subst'[of g U] by simp
qed
then obtain ka where ka: "k = ka ⋅ δ" "ka ∈ set Ka" using Ana.hyps(3) by auto
have "ka ∈ set ((fst ∘ Ana) a)" using ka(2) a' by simp
hence "ka ∈ N" using a(2) N_supset by auto
thus ?case using ka a(3,4) unfolding S_def by blast
qed
thus ?thesis unfolding S_def by blast
qed
subsection ‹Admissible Transactions›
definition admissible_transaction_checks where
"admissible_transaction_checks T ≡
∀x ∈ set (unlabel (transaction_checks T)).
(is_InSet x ⟶
is_Var (the_elem_term x) ∧ is_Fun_Set (the_set_term x) ∧
fst (the_Var (the_elem_term x)) = TAtom Value) ∧
(is_NegChecks x ⟶
bvars⇩s⇩s⇩t⇩p x = [] ∧
((the_eqs x = [] ∧ length (the_ins x) = 1) ∨
(the_ins x = [] ∧ length (the_eqs x) = 1))) ∧
(is_NegChecks x ∧ the_eqs x = [] ⟶ (let h = hd (the_ins x) in
is_Var (fst h) ∧ is_Fun_Set (snd h) ∧
fst (the_Var (fst h)) = TAtom Value))"
definition admissible_transaction_updates where
"admissible_transaction_updates T ≡
∀x ∈ set (unlabel (transaction_updates T)).
is_Update x ∧ is_Var (the_elem_term x) ∧ is_Fun_Set (the_set_term x) ∧
fst (the_Var (the_elem_term x)) = TAtom Value"
definition admissible_transaction_terms where
"admissible_transaction_terms T ≡
wf⇩t⇩r⇩m⇩s' arity (trms⇩l⇩s⇩s⇩t (transaction_strand T)) ∧
(∀f ∈ ⋃(funs_term ` trms_transaction T).
¬is_Val f ∧ ¬is_Abs f ∧ ¬is_PubConst f ∧ f ≠ Pair) ∧
(∀r ∈ set (unlabel (transaction_strand T)).
(∃f ∈ ⋃(funs_term ` (trms⇩s⇩s⇩t⇩p r)). is_Attack f) ⟶
is_Send r ∧ length (the_msgs r) = 1 ∧ is_Fun_Attack (hd (the_msgs r)))"
definition admissible_transaction_occurs_checks where
"admissible_transaction_occurs_checks T ≡ (
let occ_in = λx S. occurs (Var x) ∈ set (the_msgs (hd (unlabel S)));
rcvs = transaction_receive T;
snds = transaction_send T;
frsh = transaction_fresh T;
fvs = fv_transaction T
in ((∃x ∈ fvs - set frsh. fst x = TAtom Value) ⟶ (
rcvs ≠ [] ∧ is_Receive (hd (unlabel rcvs)) ∧
(∀x ∈ fvs - set frsh. fst x = TAtom Value ⟶ occ_in x rcvs))) ∧
(frsh ≠ [] ⟶ (
snds ≠ [] ∧ is_Send (hd (unlabel snds)) ∧
(∀x ∈ set frsh. occ_in x snds))) ∧
(∀t ∈ trms⇩l⇩s⇩s⇩t snds.
OccursFact ∈ funs_term t ∨ OccursSec ∈ funs_term t ⟶
(∃x ∈ set (transaction_fresh T). t = occurs (Var x)))
)"
definition admissible_transaction where
"admissible_transaction T ≡ (
wellformed_transaction T ∧
transaction_decl T () = [] ∧
list_all (λx. fst x = TAtom Value) (transaction_fresh T) ∧
(∀x ∈ vars_transaction T. is_Var (fst x) ∧ (the_Var (fst x) = Value)) ∧
bvars⇩l⇩s⇩s⇩t (transaction_strand T) = {} ∧
set (transaction_fresh T) ⊆
fv⇩l⇩s⇩s⇩t (filter (is_Insert ∘ snd) (transaction_updates T)) ∪ fv⇩l⇩s⇩s⇩t (transaction_send T) ∧
(∀x ∈ fv_transaction T - set (transaction_fresh T).
∀y ∈ fv_transaction T - set (transaction_fresh T).
x ≠ y ⟶ ⟨Var x != Var y⟩ ∈ set (unlabel (transaction_checks T)) ∨
⟨Var y != Var x⟩ ∈ set (unlabel (transaction_checks T))) ∧
fv⇩l⇩s⇩s⇩t (transaction_updates T) ∪ fv⇩l⇩s⇩s⇩t (transaction_send T) - set (transaction_fresh T)
⊆ fv⇩l⇩s⇩s⇩t (transaction_receive T) ∪ fv⇩l⇩s⇩s⇩t (transaction_checks T) ∧
(∀r ∈ set (unlabel (transaction_checks T)).
is_Equality r ⟶ fv (the_rhs r) ⊆ fv⇩l⇩s⇩s⇩t (transaction_receive T)) ∧
fv⇩l⇩s⇩s⇩t (transaction_checks T) ⊆
fv⇩l⇩s⇩s⇩t (transaction_receive T) ∪
fv⇩l⇩s⇩s⇩t (filter (λs. is_InSet (snd s) ∧ the_check (snd s) = Assign) (transaction_checks T)) ∧
admissible_transaction_checks T ∧
admissible_transaction_updates T ∧
admissible_transaction_terms T ∧
admissible_transaction_occurs_checks T
)"
lemma admissible_transactionE:
assumes T: "admissible_transaction T"
shows "transaction_decl T () = []" (is ?A)
and "∀x ∈ set (transaction_fresh T). Γ⇩v x = TAtom Value" (is ?B)
and "∀x ∈ vars⇩l⇩s⇩s⇩t (transaction_strand T). Γ⇩v x = TAtom Value" (is ?C)
and "bvars⇩l⇩s⇩s⇩t (transaction_strand T) = {}" (is ?D1)
and "fv_transaction T ∩ bvars_transaction T = {}" (is ?D2)
and "set (transaction_fresh T) ⊆
fv⇩l⇩s⇩s⇩t (filter (is_Insert ∘ snd) (transaction_updates T)) ∪ fv⇩l⇩s⇩s⇩t (transaction_send T)"
(is ?E)
and "set (transaction_fresh T) ⊆ fv⇩l⇩s⇩s⇩t (transaction_updates T) ∪ fv⇩l⇩s⇩s⇩t (transaction_send T)"
(is ?F)
and "∀x ∈ fv_transaction T - set (transaction_fresh T).
∀y ∈ fv_transaction T - set (transaction_fresh T).
x ≠ y ⟶ ⟨Var x != Var y⟩ ∈ set (unlabel (transaction_checks T)) ∨
⟨Var y != Var x⟩ ∈ set (unlabel (transaction_checks T))"
(is ?G)
and "∀x ∈ fv⇩l⇩s⇩s⇩t (transaction_checks T).
x ∈ fv⇩l⇩s⇩s⇩t (transaction_receive T) ∨
(∃t s. select⟨t,s⟩ ∈ set (unlabel (transaction_checks T)) ∧ x ∈ fv t ∪ fv s)"
(is ?H)
and "fv⇩l⇩s⇩s⇩t (transaction_updates T) ∪ fv⇩l⇩s⇩s⇩t (transaction_send T) - set (transaction_fresh T) ⊆
fv⇩l⇩s⇩s⇩t (transaction_receive T) ∪ fv⇩l⇩s⇩s⇩t (transaction_checks T)"
(is ?I)
and "∀x ∈ set (unlabel (transaction_checks T)).
is_Equality x ⟶ fv (the_rhs x) ⊆ fv⇩l⇩s⇩s⇩t (transaction_receive T)"
(is ?J)
and "set (transaction_fresh T) ∩ fv⇩l⇩s⇩s⇩t (transaction_receive T) = {}" (is ?K1)
and "set (transaction_fresh T) ∩ fv⇩l⇩s⇩s⇩t (transaction_checks T) = {}" (is ?K2)
and "list_all (λx. fst x = Var Value) (transaction_fresh T)" (is ?K3)
and "∀x ∈ vars_transaction T. ¬TAtom AttackType ⊑ Γ⇩v x" (is ?K4)
proof -
show ?A ?D1 ?D2 ?G ?I ?J ?K3
using T unfolding admissible_transaction_def
by (blast, blast, blast, blast, blast, blast, blast)
have "list_all (λx. fst x = Var Value) (transaction_fresh T)"
"∀x∈vars_transaction T. is_Var (fst x) ∧ the_Var (fst x) = Value"
using T unfolding admissible_transaction_def by (blast, blast)
thus ?B ?C ?K4 using Γ⇩v_TAtom''(2) unfolding list_all_iff by (blast, force, force)
show ?E using T unfolding admissible_transaction_def by argo
thus ?F unfolding unlabel_def by auto
show ?K1 ?K2
using T unfolding admissible_transaction_def wellformed_transaction_def by (argo, argo)
let ?selects = "filter (λs. is_InSet (snd s) ∧ the_check (snd s) = Assign) (transaction_checks T)"
show ?H
proof
fix x assume "x ∈ fv⇩l⇩s⇩s⇩t (transaction_checks T)"
hence "x ∈ fv⇩l⇩s⇩s⇩t (transaction_receive T) ∨ x ∈ fv⇩l⇩s⇩s⇩t ?selects"
using T unfolding admissible_transaction_def by blast
thus "x ∈ fv⇩l⇩s⇩s⇩t (transaction_receive T) ∨
(∃t s. select⟨t,s⟩ ∈ set (unlabel (transaction_checks T)) ∧ x ∈ fv t ∪ fv s)"
proof
assume "x ∈ fv⇩l⇩s⇩s⇩t ?selects"
then obtain r where r: "x ∈ fv⇩s⇩s⇩t⇩p r" "r ∈ set (unlabel (transaction_checks T))"
"is_InSet r" "the_check r = Assign"