(***************************************************************************** * ESPL --- an embedded security protocol logic * http://people.inf.ethz.ch/meiersi/espl/ * * Copyright (c) 2009-2011, Simon Meier, ETH Zurich, Switzerland * * Extension to compromising adversaries: * * Copyright (c) 2010-2011, Martin Schaub, ETH Zurich, Switzerland * * All rights reserved. See file LICENCE for more information. ******************************************************************************) theory ExplicitModel imports HOL_ext Hints Protocol ExecMessage begin chapter{* Security Proofs *} section{* Explicit Execution Model *} datatype rawevent = Step "tid \ rolestep" | Learns "execmsg set" | LKReveal id datatype reveal = RCompr notetype tid | RLKR execmsg type_synonym explicit_trace = "rawevent list" type_synonym execstep = "tid \ rolestep" type_synonym threadpool = "tid \ (rolestep list \ rolestep list \ rolestep set)" fun knows :: "explicit_trace \ execmsg set" where "knows [] = {}" | "knows (Learns M # t) = M \ knows t" | "knows (Step estep # t) = knows t" | "knows (LKReveal a # t) = knows t" fun steps :: "explicit_trace \ execstep set" where "steps [] = {}" | "steps (Learns M # t) = steps t" | "steps (Step estep # t) = insert estep (steps t)" | "steps (LKReveal a # t) = steps t" fun reveals :: "explicit_trace \ reveal set" where "reveals (Step (i, s) # xs) = (if (noteStep s) then insert (RCompr (noteType s) i) (reveals xs) else reveals xs)" | "reveals (Learns m # xs) = reveals xs" | "reveals (LKReveal a # xs) = insert (RLKR (Lit (EAgent a))) (reveals xs)" | "reveals [] = {}" fun lkreveals :: "explicit_trace \ execmsg set" where "lkreveals [] = {}" | "lkreveals (Learns M # t) = lkreveals t" | "lkreveals (Step estep # t) = lkreveals t" | "lkreveals (LKReveal a # t) = insert (Lit (EAgent a)) (lkreveals t)" definition longTermKeys :: "id \ execmsg set" where "longTermKeys a = { SK (Lit (EAgent a)) } \ { K (Lit (EAgent a)) b | b. b \ Agent } \ { K b (Lit (EAgent a)) | b. b \ Agent } \ { KShr A | A. a \ A }" lemma SK_in_longTermKeys [iff]: "(SK x \ longTermKeys a) = (x = (Lit (EAgent a)))" by (auto simp: longTermKeys_def) lemma K_in_longTermKeys [iff]: "(K x y \ longTermKeys a) = ( (x = (Lit (EAgent a)) \ y \ Agent) \ (y = (Lit (EAgent a)) \ x \ Agent) )" by (auto simp: longTermKeys_def) lemma KShr_in_longTermKeys [iff]: "(KShr A \ longTermKeys a) = (a \ A)" by (auto simp: longTermKeys_def) lemma notin_longTermKeys [iff]: "Hash m \ longTermKeys a" "Tup x y \ longTermKeys a" "Enc m k \ longTermKeys a" by (auto simp: longTermKeys_def) lemma longTermKeys_conv: "(m \ longTermKeys a) = ( (m = SK (Lit (EAgent a))) \ (\ b \ Agent. m = K (Lit (EAgent a)) b \ m = K b (Lit (EAgent a)) ) \ (\ A. m = KShr A \ a \ A) )" by (auto simp: longTermKeys_def) type_synonym state = "explicit_trace \ threadpool \ store" inductive_set reachable :: "proto \ state set" for P :: "proto" where init: "\ \ i done todo skipped. r i = Some (done,todo,skipped) \ done = [] \ skipped = {} \ todo \ P; \ a i. s (AVar a, i) \ Agent \ \ ([Learns IK0], r, s) \ reachable P" | compr: "\ (t, r, s) \ reachable P; r i = Some (done, Note l ty pt # todo, skipped); Some m = inst s i pt \ \ (t @ [Step (i,Note l ty pt), Learns (pairParts m - knows t)], r(i \ (done @ [Note l ty pt], todo, skipped)), s) \ reachable P" | skip: "\ (t, r, s) \ reachable P; r i = Some (done, Note l ty pt # todo, skipped) \ \ (t, r(i \ (done @ [Note l ty pt], todo, insert (Note l ty pt) skipped)), s) \ reachable P" | lkr: "\ (t, r, s) \ reachable P; LKReveal a \ set t \ \ (t @ [LKReveal a, Learns (longTermKeys a - knows t)], r, s) \ reachable P" | send: "\ (t, r, s) \ reachable P; r i = Some (done, Send l pt # todo, skipped); Some m = inst s i pt \ \ (t @ [Step (i, Send l pt), Learns (pairParts m - knows t)], r(i \ (done @ [Send l pt], todo, skipped)), s) \ reachable P" | recv: "\ (t, r, s) \ reachable P; r i = Some (done, Recv l pt # todo, skipped); Some m = inst s i pt; m \ knows t \ \ (t @ [Step (i, Recv l pt)], r(i \ (done @ [Recv l pt], todo, skipped)), s) \ reachable P" | hash: "\ (t, r, s) \ reachable P; m \ knows t; Hash m \ knows t \ \ (t @ [Learns {Hash m}], r, s) \ reachable P" | tuple: "\ (t, r, s) \ reachable P; x \ knows t; y \ knows t; Tup x y \ knows t \ \ (t @ [Learns {Tup x y}], r, s) \ reachable P" | encr: "\ (t, r, s) \ reachable P; m \ knows t; k \ knows t; Enc m k \ knows t \ \ (t @ [Learns {Enc m k}], r, s) \ reachable P" | decr: "\ (t, r, s) \ reachable P; Enc m k \ knows t; inv k \ knows t \ \ (t @ [Learns (pairParts m - knows t)], r, s) \ reachable P" locale reachable_state = wf_proto + fixes t :: explicit_trace and r :: threadpool and s :: store assumes reachable [simp,intro!]: "(t,r,s) \ reachable P" begin text{* A local variant of the induction rule of @{term "reachable"}. *} lemmas reachable_induct = reachable.induct [ OF reachable , rule_format , consumes 0 , case_names init compr skip lkr send recv hash tuple encr decr ] end text{* An extension of the reachable state locale denoting an individual thread and its state. *} locale reachable_thread = reachable_state + fixes i :: "tid" and "done" :: "rolestep list" and todo :: "rolestep list" and skipped :: "rolestep set" assumes thread_exists: "r i = Some (done, todo, skipped)" begin text{* The thread state is built such that @{term "done @ todo"} is always a role of @{term P}. *} lemma role_in_P: "done @ todo \ P" using thread_exists proof (induct arbitrary: i "done" todo skipped rule: reachable_induct) qed (fastforce split: if_splits)+ end text{* Importing all lemmas of the wellformed role locale for the term @{term "done @ todo"}. *} sublocale reachable_thread \ wf_role "done @ todo" by (rule wf_roles[OF role_in_P]) subsection{* Basic Properties *} lemma knowsI: "\ Learns M \ set t; m \ M \ \ m \ knows t" by(induct t rule: knows.induct, auto) lemma knowsD: "m \ knows t \ \ M. Learns M \ set t \ m \ M" by(induct t rule: steps.induct, auto) lemma knows_append [simp]: "knows (xs@ys) = knows xs \ knows ys" by(induct xs rule: knows.induct, auto) lemma stepsI: "Step estep \ set t \ estep \ steps t" by(induct t rule: steps.induct, auto) lemma stepsD: "estep \ steps t \ Step estep \ set t" by(induct t rule: steps.induct, auto) lemma Step_in_set_conv [simp]: "(Step estep \ set t) = (estep \ steps t)" by(auto intro!: stepsI stepsD) lemma steps_append [simp]: "steps (t@t') = steps t \ steps t'" by(induct t rule: steps.induct, auto) lemma lkrevealsI: "LKReveal a \ set t \ (Lit (EAgent a)) \ lkreveals t" by(induct t rule: lkreveals.induct, auto) lemma lkrevealsD: "(Lit (EAgent a)) \ lkreveals t \ LKReveal a \ set t" by(induct t rule: lkreveals.induct, auto) lemma Lkr_in_set_conv [simp]: "(LKReveal a \ set t) = ((Lit (EAgent a)) \ lkreveals t)" by(auto intro!: lkrevealsI lkrevealsD) lemma lkreveals_append [simp]: "lkreveals (t@t') = lkreveals t \ lkreveals t'" by(induct t rule: lkreveals.induct, auto) lemma lkreveals_agent: "a \ lkreveals t \ \ b. a = (Lit (EAgent b))" by(induct t rule: lkreveals.induct, auto) subsection{* Thread Execution *} lemma (in reachable_state) step_in_dom: "(i, step) \ steps t \ i \ dom r" proof (induct rule: reachable_induct) qed auto lemma reveals_Nil[dest!]: "a \ reveals [] \ False" by (auto) lemma reveals_append [simp]: "reveals (xs@ys) = reveals xs \ reveals ys" by(induct xs rule: reveals.induct, auto) lemma RLKR_lkreveals_conv: "(RLKR a \ reveals t) = (a \ lkreveals t)" proof(induct t rule: reveals.induct) case (1 i s xs) thus ?case by force qed auto lemma steps_to_reveals: "(i, Note l ty pt) \ steps t \ RCompr ty i \ reveals t" by(induct t rule: reveals.induct) (auto) lemma reveals_to_steps: "RCompr ty i \ reveals t \ \ l pt. (i, Note l ty pt) \ steps t" proof(induct t rule: reveals.induct) case (1 i' s xs) thus ?case by (cases s) auto qed auto lemma RCompr_steps_conv: "RCompr ty i \ reveals t = (\ l pt. (i, Note l ty pt) \ steps t)" by (fastforce intro: reveals_to_steps steps_to_reveals) context reachable_thread begin lemma in_dom_r [iff]: "i \ dom r" by (auto intro!: thread_exists) lemma distinct_done [iff]: "distinct done" using distinct by auto lemma skipped_in_done: "step \ skipped \ step \ set done" using thread_exists proof (induct arbitrary: i "done" skipped todo rule: reachable_induct) qed (auto split: if_splits)+ lemma distinct_todo [iff]: "distinct todo" using distinct by auto (* Proofs of the relationship between steps, skipped and done ********************************************************************************************) lemma note_in_skipped: "\ step \ skipped \ \ \ l ty pt. (step = (Note l ty pt))" using thread_exists proof(induct arbitrary: i "done" todo skipped rule: reachable_induct) case init thus "?case" by fastforce qed( auto split: if_splits) lemma send_notin_skipped [iff]: "Send l pt \ skipped" by (auto dest!: note_in_skipped) lemma recv_notin_skipped [iff]: "Recv l pt \ skipped" by (auto dest!: note_in_skipped) lemma in_steps_conv_done_skipped: "(i, step) \ steps t = (step \ set done \ step \ skipped)" using thread_exists using distinct proof(induct arbitrary: i "done" todo skipped rule: reachable_induct) case init thus ?case by fastforce next case (send t r s i "done" l pt todo skipped m i' done' todo' skipped') thus ?case proof(cases "i = i'") case True then interpret thread: reachable_thread P t r s i "done" "Send l pt # todo" skipped' using send by unfold_locales auto show ?thesis using send `i = i'` by fastforce qed auto next case (recv t r s i "done" l pt todo skipped m i' done' todo' skipped') thus ?case proof(cases "i = i'") case True then interpret thread: reachable_thread P t r s i "done" "Recv l pt # todo" skipped' using recv by unfold_locales auto show ?thesis using recv `i = i'` by fastforce qed auto next case (compr t r s i "done" l ty pt todo skipped m i' done' todo' skipped') thus ?case proof(cases "i = i'") case True thus ?thesis using compr `i = i'` proof(cases "step = Note l ty pt") case True interpret thread: reachable_thread P t r s i "done" "Note l ty pt # todo" skipped' using compr `i = i'` by unfold_locales auto show ?thesis using compr `i = i'` `step = Note l ty pt` by (fastforce dest: thread.skipped_in_done ) qed fastforce qed auto next case(skip t r s i "done" l ty pt todo skipped i' done' todo' skipped') thus ?case proof(cases "i = i'") case True thus ?thesis using skip `i = i'` proof(cases "step = Note l ty pt") case True interpret thread: reachable_thread P t r s i "done" "Note l ty pt # todo" skipped using skip `i = i'` by unfold_locales auto show ?thesis using skip `i = i'` `step = Note l ty pt` by fastforce qed fastforce qed auto qed auto lemma in_steps_recv: "((Recv l pt) \ set done) = ((i,Recv l pt) \ steps t)" using thread_exists proof(induct arbitrary: i "done" todo skipped rule rule: reachable_induct) case init thus "?case" by fastforce qed ((unfold map_upd_Some_unfold)?, auto)+ lemma in_steps_send: "((Send l pt) \ set done) = ((i,Send l pt) \ steps t)" using thread_exists proof(induct arbitrary: i "done" todo skipped rule rule: reachable_induct) case init thus "?case" by fastforce qed ((unfold map_upd_Some_unfold)?, auto)+ lemmas send_steps_in_done [elim!] = iffD1[OF in_steps_send, rule_format] lemmas send_done_in_steps [elim!] = iffD2[OF in_steps_send, rule_format] lemmas recv_steps_in_done [elim!] = iffD1[OF in_steps_recv, rule_format] lemmas recv_done_in_steps [elim!] = iffD2[OF in_steps_recv, rule_format] lemma in_steps_eq_in_done: "step \ skipped \ ((i, step) \ steps t) = (step \ set done)" using thread_exists by(auto simp add: in_steps_conv_done_skipped) lemma todo_notin_doneD: "step \ set todo \ step \ set done" using distinct using role_in_P by(auto) lemma done_notin_todoD: "step \ set done \ step \ set todo" using distinct using role_in_P by(auto) lemma todo_notin_skippedD: "step \ set todo \ step \ skipped" using distinct using role_in_P by(fastforce dest: skipped_in_done) lemma skipped_notin_todoD: "step \ skipped \ step \ set todo" using distinct using role_in_P by(fastforce dest: skipped_in_done) lemma notin_steps_notin_trace: "(i, step) \ steps t \ (Step (i, step)) \ set t" by(auto) lemma in_steps_in_done: assumes inSteps: "(i, step) \ steps t" shows "step \ set done" proof(cases step) case (Send l pt) thus ?thesis using inSteps by (fastforce dest: in_steps_send[THEN iffD2]) next case (Recv l pt) thus ?thesis using inSteps by (fastforce dest: in_steps_recv[THEN iffD2]) next case (Note l ty pt) thus ?thesis using inSteps by (fastforce simp add: in_steps_conv_done_skipped) qed lemma step_notin_skippedD [dest]: "\ step \ skipped; (i, step) \ steps t \ \ False" by(auto simp add: in_steps_conv_done_skipped) lemma notin_skipped_notin_steps [dest]: "\ step \ set done; (i, step) \ steps t; step \ skipped \ \ False" by(auto simp add: in_steps_conv_done_skipped) lemma[dest]: "\ step \ set todo; step \ set done \ \ False" by(fastforce dest: todo_notin_doneD) lemma[dest]: "\ step \ set todo; step \ skipped \ \ False" by(auto dest: todo_notin_skippedD) lemma[dest]: "\ (i, step) \ steps t; (Step (i, step)) \ set t \ \ False" by(auto) lemma[dest]: "\ (i, step) \ steps t; (Step (i, step)) \ set t \ \ False" by(auto) lemma listOrd_done_imp_listOrd_trace: assumes facts: "listOrd done prev step" "prev \ skipped" "step \ skipped" shows stepOrd: "listOrd t (Step (i, prev)) (Step (i, step))" using thread_exists using facts proof(induct arbitrary: i "done" todo skipped rule: reachable_induct) case (init r s i "done" todo) thus ?case by fastforce next case (send t r s i "done" l msg todo skipped m i' done' todo' skipped') thus ?case using send proof(cases "i = i'") case True interpret this_thread: reachable_thread P t r s i' "done" "Send l msg # todo'" skipped' using send `i = i'` by unfold_locales auto show?thesis using send `i = i'` by fastforce qed fastforce next case (recv t r s i "done" l msg todo skipped m i' done' todo' skipped') from recv show ?case proof(cases "i = i'") case True interpret this_thread: reachable_thread P t r s i' "done" "Recv l msg # todo'" skipped' using recv `i = i'` by unfold_locales auto show ?thesis using recv `i = i'` by fastforce qed fastforce next case (compr t r s i "done" l ty msg todo skipped m i' done' todo' skipped') from compr show ?case proof(cases "i = i'") case True interpret this_thread: reachable_thread P t r s i' "done" "Note l ty msg # todo'" skipped' using compr `i = i'` by unfold_locales auto show ?thesis using compr `i = i'` by fastforce qed fastforce next case (skip t r s i "done" l ty msg todo skipped i' done' todo' skipped') from skip show ?case proof(cases "i = i'") case True then interpret this_thread: reachable_thread P t r s i "done" "Note l ty msg # todo" skipped using skip `i = i'` by unfold_locales auto show ?thesis using skip `i = i'` by fastforce qed fastforce qed auto lemma listOrd_recv_role_imp_listOrd_trace: assumes facts: "(i, step) \ steps t" "listOrd (done @ todo) (Recv l pt) step" shows rtOrd: "listOrd t (Step (i, Recv l pt)) (Step (i, step))" using distinct using facts by(auto dest: in_set_listOrd1 todo_notin_doneD listOrd_done_imp_listOrd_trace in_set_listOrd2 listOrd_append[THEN iffD1] in_steps_conv_done_skipped[THEN iffD1]) lemma listOrd_send_role_imp_listOrd_trace: assumes facts: "(i, step) \ steps t" "listOrd (done @ todo) (Send l pt) step" shows stOrd: "listOrd t (Step (i, Send l pt)) (Step (i, step))" using distinct using facts by(auto dest: in_set_listOrd1 todo_notin_doneD listOrd_done_imp_listOrd_trace in_set_listOrd2 listOrd_append[THEN iffD1] in_steps_conv_done_skipped[THEN iffD1]) lemma roleOrd_notSkipped_imp_listOrd_trace: assumes facts: "(i, step) \ steps t" "step' \ skipped" "listOrd (done @ todo) step' step" shows "listOrd t (Step (i, step')) (Step (i, step))" using distinct using facts by(auto dest: in_set_listOrd1 todo_notin_doneD listOrd_done_imp_listOrd_trace in_set_listOrd2 listOrd_append[THEN iffD1] in_steps_conv_done_skipped[THEN iffD1]) end subsection{* Variable Substitutions *} context reachable_state begin lemma inst_AVar_cases: "s (AVar v, i) \ Agent" by (induct rule: reachable_induct, auto) lemma inst_AVar_in_IK0: "s (AVar v, i) \ IK0" using inst_AVar_cases[of v i] by (auto simp: IK0_def Agent_def) lemma knows_IK0: "m \ IK0 \ m \ knows t" by(induct rule: reachable_induct, auto) lemma inst_AVar_in_knows [iff]: "s (AVar a, i) \ knows t" by (rule knows_IK0[OF inst_AVar_in_IK0]) end (* reachable_state *) lemma (in reachable_state) send_step_FV: assumes thread_exists: "r i = Some (done, Send l msg # todo, skipped)" and FV: "MVar n \ FV msg" shows "\ l' msg'. (i, Recv l' msg') \ steps t \ MVar n \ FV msg'" proof - interpret this_thread: reachable_thread P t r s i "done" "Send l msg # todo" skipped using thread_exists by unfold_locales auto let ?role = "done @ Send l msg # todo" have "Send l msg \ set ?role" by simp then obtain l' msg' where "listOrd ?role (Recv l' msg') (Send l msg)" and "MVar n \ FV msg'" using FV by(fast dest!: this_thread.Send_FV) thus ?thesis using this_thread.distinct by(auto dest: in_set_listOrd1 in_set_listOrd2) qed lemma (in reachable_state) note_step_FV: assumes thread_exists: "r i = Some (done, Note l ty msg # todo, skipped)" and FV: "MVar n \ FV msg" shows "\ l' msg'. (i, Recv l' msg') \ steps t \ MVar n \ FV msg'" proof - interpret this_thread: reachable_thread P t r s i "done" "Note l ty msg # todo" skipped using thread_exists by unfold_locales auto let ?role = "done @ Note l ty msg # todo" have "Note l ty msg \ set ?role" by simp then obtain l' msg' where "listOrd ?role (Recv l' msg') (Note l ty msg)" and "MVar n \ FV msg'" using FV by(fast dest!: this_thread.Note_FV) thus ?thesis using this_thread.distinct by(auto dest: in_set_listOrd1 in_set_listOrd2) qed subsubsection{* The Effect of a Step on the Intruder Knowledge *} context reachable_state begin lemma SendD: "(i, Send lbl pt) \ steps t \ (\ m. Some m = inst s i pt \ m \ knows t)" proof(induct rule: reachable_induct) qed auto end subsection{* Almost Distinct Traces *} fun distinct' :: "explicit_trace \ bool" where "distinct' [] = True" | "distinct' (Learns M # t) = ((\ m \ M. m \ knows t) \ distinct' t)" | "distinct' (Step estep # t) = ((estep \ steps t) \ distinct' t)" | "distinct' (LKReveal a # t) = (((Lit (EAgent a)) \ lkreveals t) \ distinct' t)" lemma distinct'_append [simp]: "distinct' (t@t') = (distinct' t \ distinct' t' \ (knows t \ knows t' = {}) \ (steps t \ steps t' = {}) \ (lkreveals t \ lkreveals t') = {})" proof (induct t rule: distinct'.induct) qed (auto intro!: knowsI) lemma distinct'_singleton [iff]: "distinct' [x]" by (cases x) auto lemma (in reachable_state) distinct'_trace [iff]: "distinct' t" proof(induct arbitrary: i "done" todo skipped rule: reachable_induct) case (recv t r s i "done" l msg todo skipped) then interpret this_thread: reachable_thread P t r s i "done" "Recv l msg # todo" skipped by unfold_locales auto show ?case using `distinct' t` this_thread.distinct by(fastforce dest: this_thread.in_steps_in_done) next case (send t r s i "done" l msg todo skipped m) then interpret this_thread: reachable_thread P t r s i "done" "Send l msg # todo" skipped by unfold_locales auto show ?case using `distinct' t` and this_thread.distinct by(fastforce dest: this_thread.in_steps_in_done) next case (compr t r s i "done" l ty msg todo skipped m) then interpret this_thread: reachable_thread P t r s i "done" "Note l ty msg # todo" skipped by unfold_locales auto show ?case using `distinct' t` and this_thread.distinct by(fastforce dest: this_thread.in_steps_in_done) next case (skip t r s i "done" l ty msg todo skipped) then interpret this_thread: reachable_thread P t r s i "done" "Note l ty msg # todo" skipped by unfold_locales auto show ?case using `distinct' t` and this_thread.distinct by(auto) qed auto subsection{* Happens-Before Order *} datatype event = St "tid \ rolestep" | Ln execmsg | LKR execmsg fun predOrd :: "explicit_trace \ event \ event \ bool" where "predOrd [] x y = False" | "predOrd (Learns M # xs) x y = ((x \ Ln ` M \ (y \ Ln ` knows xs \ y \ St ` steps xs \ y \ LKR ` lkreveals xs)) \ predOrd xs x y)" | "predOrd (Step estep # xs) x y = ((x = St estep \ (y \ Ln ` knows xs \ y \ St ` steps xs \ y \ LKR ` lkreveals xs)) \ predOrd xs x y)" | "predOrd (LKReveal a # xs) x y = ((x = LKR (Lit (EAgent a)) \ (y \ Ln ` knows xs \ y \ St ` steps xs \ y \ LKR ` lkreveals xs)) \ predOrd xs x y)" definition predEqOrd :: "explicit_trace \ event \ event \ bool" where "predEqOrd t x y = ((x = y) \ predOrd t x y)" lemma predOrd_singleton [simp]: "\ predOrd [a] x y" by (cases a) auto lemma in_knows_predOrd1: "predOrd t (Ln x) y \ x \ knows t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_knows_predOrd2: "predOrd t x (Ln y) \ y \ knows t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_steps_predOrd1: "predOrd t (St x) y \ x \ steps t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_steps_predOrd2: "predOrd t x (St y) \ y \ steps t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_lkreveals_predOrd1: "predOrd t (LKR x) y \ x \ lkreveals t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_lkreveals_predOrd2: "predOrd t x (LKR y) \ y \ lkreveals t" proof (induct t) case (Cons e t) thus ?case by (cases e) auto qed auto lemma in_reveals_predOrd1: assumes facts: "predOrd t (St (i, st)) e" "noteStep st" shows "RCompr (noteType st) i \ reveals t" using facts by(force dest: noteStepD intro: RCompr_steps_conv[THEN iffD2] in_steps_predOrd1) lemma in_reveals_predOrd2: assumes facts: "predOrd t e (St (i, st))" "noteStep st" shows "RCompr (noteType st) i \ reveals t" using facts by(force dest: noteStepD intro: RCompr_steps_conv[THEN iffD2] in_steps_predOrd2) lemma note_in_reveals_predOrd1: assumes facts: "predOrd t (St (i, Note l ty pt)) e" shows "RCompr ty i \ reveals t" using facts by(force dest: noteStepD intro: RCompr_steps_conv[THEN iffD2] in_steps_predOrd1) lemma note_in_reveals_predOrd2: assumes facts: "predOrd t e (St (i, Note l ty pt))" shows "RCompr ty i \ reveals t" using facts by(force dest: noteStepD intro: RCompr_steps_conv[THEN iffD2] in_steps_predOrd2) lemma lkr_in_reveals_predOrd1: "predOrd t (LKR a) e \ RLKR a \ reveals t" by(force intro: RLKR_lkreveals_conv[THEN iffD2] in_lkreveals_predOrd1) lemma lkr_in_reveals_predOrd2: "predOrd t e (LKR a) \ RLKR a \ reveals t" by(force intro: RLKR_lkreveals_conv[THEN iffD2] in_lkreveals_predOrd2) lemmas event_predOrdI = in_knows_predOrd1 in_knows_predOrd2 in_steps_predOrd1 in_steps_predOrd2 lemmas compr_predOrdI = lkr_in_reveals_predOrd1 lkr_in_reveals_predOrd2 note_in_reveals_predOrd1 note_in_reveals_predOrd2 lemma event_predOrdE: "\predOrd t (Ln x) (Ln y); \ x \ knows t; y \ knows t \ \ R \ \ R" "\predOrd t (Ln x) (St b); \ x \ knows t; b \ steps t \ \ R \ \ R" "\predOrd t (St a) (Ln y); \ a \ steps t; y \ knows t \ \ R \ \ R" "\predOrd t (St a) (St b); \ a \ steps t; b \ steps t \ \ R \ \ R" "\predOrd t (LKR c) (Ln y); \ RLKR c \ reveals t; y \ knows t \ \ R \ \ R" "\predOrd t (LKR c) (St b); \ RLKR c \ reveals t; b \ steps t \ \ R \ \ R" "\predOrd t (St a) (LKR d); \ a \ steps t; RLKR d \ reveals t \ \ R \ \ R" "\predOrd t (Ln x) (LKR d); \ x \ knows t; RLKR d \ reveals t \ \ R \ \ R" "\predOrd t (LKR c) (LKR d); \ RLKR c \ reveals t; RLKR d \ reveals t \ \ R \ \ R" by(fastforce intro: event_predOrdI compr_predOrdI)+ lemma predOrd_LKR_agent1: "predOrd t (LKR a) b \ \ c. a = (Lit (EAgent c))" by(auto dest!: lkreveals_agent RLKR_lkreveals_conv[THEN iffD1] dest: compr_predOrdI ) lemma predOrd_LKR_agent2: "predOrd t b (LKR a) \ \ c. a = (Lit (EAgent c))" by(auto dest!: lkreveals_agent RLKR_lkreveals_conv[THEN iffD1] dest: compr_predOrdI ) lemma in_set_predOrd1: "predOrd t x y \ x \ Ln ` knows t \ x \ St ` steps t \ x \ LKR ` lkreveals t" by (induct t x y rule: predOrd.induct) auto lemma in_set_predOrd2: "predOrd t x y \ y \ Ln ` knows t \ y \ St ` steps t \ y \ LKR ` lkreveals t" by (induct t x y rule: predOrd.induct) auto lemma listOrd_imp_predOrd: "listOrd t (Step e) (Step e') \ predOrd t (St e) (St e')" by (induct t rule: steps.induct) (auto dest!: stepsI) lemma predOrd_append [simp]: "predOrd (xs@ys) x y = (predOrd xs x y \ predOrd ys x y \ ((x \ Ln ` knows xs \ x \ St ` steps xs \ x \ LKR ` lkreveals xs) \ (y \ Ln ` knows ys \ y \ St ` steps ys \ y \ LKR ` lkreveals ys)))" apply(induct xs x y rule: predOrd.induct) apply(simp_all) apply(blast+) done lemma predOrd_distinct'_irr [simp]: "distinct' t \ \predOrd t x x" apply(induct t, auto) apply(case_tac x, auto) apply(case_tac a, auto) apply(case_tac a, auto) apply(case_tac a, auto) done lemma predOrd_distinct'_trans: "\ predOrd t x y; predOrd t y z; distinct' t \ \ predOrd t x z" apply(induct t x y rule: predOrd.induct) apply(auto dest: in_set_predOrd1 in_set_predOrd2) done lemma predOrd_distinct'_asymD: "\ predOrd t x y; distinct' t \ \ \ predOrd t y x" apply(induct t x y rule: predOrd.induct) apply(auto dest: in_set_predOrd1 in_set_predOrd2) done sublocale reachable_state \ beforeOrd: order "predEqOrd t" "predOrd t" apply(unfold_locales) apply(auto simp: predEqOrd_def dest: predOrd_distinct'_asymD intro: predOrd_distinct'_trans) done abbreviation (in reachable_state) "pred'" (infixl "\" 50) where "pred' \ predOrd t" abbreviation (in reachable_state) "predEq'" (infixl "\" 50) where "predEq' \ predEqOrd t" lemma predOrd_conv: "predOrd xs x y = (\ ys zs. xs = ys @ zs \ (x \ Ln ` knows ys \ x \ St ` steps ys \ x \ LKR ` lkreveals ys) \ (y \ Ln ` knows zs \ y \ St ` steps zs \ y \ LKR ` lkreveals zs))" (is "?pred xs = (\ ys zs. ?decomp xs ys zs)") proof - { assume "?pred xs" hence "\ ys zs. ?decomp xs ys zs" proof (induct xs) case Nil thus ?case by simp next case (Cons e xs) thus ?case proof(cases e) case (Step st) thus ?thesis proof(cases "x = St st") case True hence "?decomp (e#xs) [e] xs" using Step Cons by auto thus ?thesis by blast next case False hence "predOrd xs x y" using Step Cons by auto then obtain ys zs where "?decomp xs ys zs" using Cons by blast hence "?decomp (e#xs) (e#ys) zs" using Step Cons by auto thus ?thesis by blast qed next case (Learns M) thus ?thesis proof(cases "\ m \ M. x = Ln m") case True then obtain m where "m \ M" and "x = Ln m" by auto hence "?decomp (e#xs) [e] xs" using Learns Cons by auto thus ?thesis by blast next case False hence "predOrd xs x y" using Learns Cons by auto then obtain ys zs where "?decomp xs ys zs" using Cons by blast hence "?decomp (e#xs) (e#ys) zs" using Learns Cons by auto thus ?thesis by blast qed next case (LKReveal a) thus ?thesis proof(cases "x = LKR (Lit (EAgent a))") case True hence "?decomp (e#xs) [e] xs" using LKReveal Cons by auto thus ?thesis by blast next case False hence "predOrd xs x y" using LKReveal Cons by auto then obtain ys zs where "?decomp xs ys zs" using Cons by blast hence "?decomp (e#xs) (e#ys) zs" using LKReveal Cons by auto thus ?thesis by blast qed qed qed } moreover { assume "\ ys zs. ?decomp xs ys zs" hence "?pred xs" proof (induct xs) case Nil thus ?case by simp next case (Cons e xs) then obtain ys zs where decomp1: "?decomp (e#xs) ys zs" by blast hence "ys = [] \ e # xs = zs \ (\ys'. e # ys' = ys \ xs = ys' @ zs)" (is "?nil \ ?non_nil") by (simp add: Cons_eq_append_conv) moreover { assume ?nil hence ?case using decomp1 by auto } moreover { assume ?non_nil then obtain ys' where decomp2: "ys = e # ys'" and "xs = ys' @ zs" by auto hence ?case proof(cases e) case (Step st) thus ?thesis proof(cases "x = St st") case True thus ?thesis using Step decomp1 decomp2 by auto next case False hence "?decomp xs ys' zs" using Step decomp1 decomp2 by auto hence "predOrd xs x y" using Cons by auto thus ?thesis using Step by auto qed next case (Learns M) thus ?thesis proof(cases "\ m \ M. x = Ln m") case True thus ?thesis using Learns decomp1 decomp2 by auto next case False hence "?decomp xs ys' zs" using Learns decomp1 decomp2 by auto hence "predOrd xs x y" using Cons by auto thus ?thesis using Learns by auto qed next case (LKReveal a) thus ?thesis proof(cases "x = LKR (Lit (EAgent a))") case True thus ?thesis using LKReveal decomp1 decomp2 by auto next case False hence "?decomp xs ys' zs" using LKReveal decomp1 decomp2 by auto hence "predOrd xs x y" using Cons by auto thus ?thesis using LKReveal by auto qed qed } ultimately show ?case by fast qed } ultimately show ?thesis by fast qed subsection{* Input Terms *} context reachable_state begin lemma knows_pairParts_closed: "m \ knows t \ pairParts m \ knows t" proof(induct arbitrary: m rule: reachable_induct) case init thus ?case by(auto simp: IK0_def) next case send thus ?case by(auto dest: pairParts_idemD) next case decr thus ?case by(auto dest: pairParts_idemD) next case tuple thus ?case by fastforce next case lkr thus ?case by(auto simp: longTermKeys_def) next case compr thus ?case by(auto dest: pairParts_idemD) qed auto lemmas knows_pairParts_closedD = subsetD[OF knows_pairParts_closed, rule_format] lemmas rev_knows_pairParts_closedD = rev_subsetD[OF _ knows_pairParts_closed, rule_format] lemma pairParts_before: "\ predOrd t (Ln m) y; m' \ pairParts m \ \ predOrd t (Ln m') y" proof(induct rule: reachable_induct) case (hash t r s msg) then interpret s1: reachable_state P t r s by unfold_locales from hash show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (encr t r s msg key) then interpret s1: reachable_state P t r s by unfold_locales from encr show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (tuple t r s msg1 msg2) then interpret s1: reachable_state P t r s by unfold_locales from tuple show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (decr t r s msg key) then interpret s1: reachable_state P t r s by unfold_locales from decr show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (send t r s i "done" l msg todo msg) then interpret s1: reachable_state P t r s by unfold_locales from send show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (recv t r s i "done" l msg todo) then interpret s1: reachable_state P t r s by unfold_locales from recv show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (init r s) thus ?case by simp next case (lkr t r s a) then interpret s1: reachable_state P t r s by unfold_locales from lkr show ?case by (fastforce dest: s1.rev_knows_pairParts_closedD) next case (skip t r s i "done" l ty pt todo) then interpret s1: reachable_state P t r s by unfold_locales from skip show ?case by(fastforce dest: s1.rev_knows_pairParts_closedD) next case (compr t r s i "done" l ty pt todo skipped m) then interpret s1: reachable_state P t r s by unfold_locales from compr show ?case by(fastforce dest: s1.rev_knows_pairParts_closedD) qed lemma Ln_before_inp: "(i, Recv l pt) \ steps t \ \ m. Some m = inst s i pt \ Ln m \ St (i, Recv l pt)" by (induct arbitrary: i l pt rule: reachable_induct) fastforce+ lemma Ln_before_inpE: "\ (i, Recv l pt) \ steps t; \ m. \ Some m = inst s i pt; Ln m \ St (i, Recv l pt) \ \ Q \ \ Q" by (auto dest!: Ln_before_inp) (* lemmas knows_inp = in_knows_predOrd1[OF Ln_before_inp, rule_format] *) text{* Three of the lemmas for the reasoning technique. *} lemmas Input = Ln_before_inp lemma split_before: "Ln (Tup m m') \ y \ Ln m \ y \ Ln m' \ y" by (fastforce intro: pairParts_before) lemma split_knows: "Tup m m' \ knows t \ m \ knows t \ m' \ knows t" by (fastforce intro: knows_pairParts_closedD) end subsection{* Case Distinction on Learning Messages *} text{* Note that the hints are logically equal to true. Thus they have no logical content. However they are placed here to track the individual cases when computing the decryption chains for a concrete message and protocol. *} fun decrChain :: "string \ explicit_trace \ event set \ execmsg \ execmsg \ bool" where "decrChain path t from (Enc msg key) m = ( ( m = Enc msg key \ (\ f \ from. predOrd t f (Ln m)) \ hint ''decrChainPath'' path ) \ ( (\ f \ from. predOrd t f (Ln (Enc msg key))) \ decrChain (path@''E'') t {Ln (Enc msg key), Ln (inv key)} msg m ) )" | "decrChain path t from (Tup x y) m = ( ( m = Tup x y \ (\ f \ from. predOrd t f (Ln m)) \ hint ''decrChainPath'' path ) \ decrChain (path@''L'') t from x m \ decrChain (path@''R'') t from y m )" | "decrChain path t from msg m = ( m = msg \ (\ f \ from. predOrd t f (Ln m)) \ hint ''decrChainPath'' path )" lemma decrChain_append: "decrChain path t from msg m \ decrChain path (t@t') from msg m" by (induct path t "from" msg m rule: decrChain.induct) auto lemma decrChain_unpair: "\ m' \ pairParts m; m' \ M; \ f \ from. f \ Ln ` knows t \ f \ St ` steps t \ \ decrChain path (t@[Learns M]) from m m'" by (induct m arbitrary: path M) (auto simp: remove_hints) lemma decrChain_decrypt: "\ decrChain path t from msg (Enc m k); Enc m k \ knows t; inv k \ knows t; m' \ pairParts m; m' \ knows t \ \ decrChain path' (t @ [Learns (pairParts m - knows t)]) from msg m'" proof(induct msg arbitrary: path path' "from") case (Enc msg key) hence from_before [simp]: "\f\from. predOrd t f (Ln (Enc msg key))" by auto have "m = msg \ k = key \ decrChain (path@''E'') t {Ln (Enc msg key), Ln (inv key)} msg (Enc m k)" (is "?here \ ?nested") using Enc by auto moreover { assume "?here" hence "?case" proof(cases "m' = Enc m k") case True thus ?thesis using `?here` Enc by fastforce next case False thus ?thesis using `?here` Enc by(auto intro!: decrChain_unpair) qed } moreover { assume "?nested" hence "?case" using Enc by (fastforce dest!: Enc(2)) } ultimately show ?case by fast qed auto lemma (in reachable_state) knows_cases_raw: assumes knows: "m' \ knows t" shows "(m' \ IK0) \ (\ m. m' = Hash m \ Ln m \ Ln (Hash m)) \ (\ m k. m' = Enc m k \ Ln m \ Ln (Enc m k) \ Ln k \ Ln (Enc m k)) \ (\ x y. m' = Tup x y \ Ln x \ Ln (Tup x y) \ Ln y \ Ln (Tup x y)) \ (\ i done todo skipped. r i = Some (done, todo, skipped) \ (\ l pt m. Send l pt \ set done \ Some m = inst s i pt \ decrChain [] t {St (i, Send l pt)} m m' ) ) \ (\ i done todo skipped. r i = Some (done, todo, skipped) \ (\ l ty pt m. Note l ty pt \ set done \ Note l ty pt \ skipped \ Some m = inst s i pt \ decrChain [] t {St (i, Note l ty pt)} m m' ) ) \ (\ a. m' = SK a \ LKR a \ Ln m') \ (\ a b. m' = K a b \ LKR a \ Ln m') \ (\ a b. m' = K a b \ LKR b \ Ln m') \ (\ A. \ a \ A. m' = KShr A \ LKR (Lit (EAgent a)) \ Ln m') " (is "?cases m' t r s") proof - --{* Prove cases transfer lemma for trace extension *} { fix m' t t' r s let ?thesis = "?cases m' (t@t') r s" assume "?cases m' t r s" (is "?ik0 \ ?hash \ ?enc \ ?tup \ ?chain t r s \ ?note t r s \ ?keys") moreover { assume "?ik0" hence "?thesis" by blast } moreover { assume "?hash" hence "?thesis" by fastforce } moreover { assume "?enc" hence "?thesis" by fastforce } moreover { assume "?tup" hence "?thesis" by fastforce } moreover { assume "?chain t r s" hence "?chain (t@t') r s" by (fastforce intro!: decrChain_append) hence "?thesis" by blast } moreover { assume "?note t r s" hence "?note (t@t') r s" by (fastforce intro!: decrChain_append) hence "?thesis" by blast } moreover { assume "?keys" hence "?thesis" by auto } ultimately have ?thesis by fast } note cases_appendI_trace = this --{* Prove actual thesis *} from knows show ?thesis proof (induct arbitrary: m' rule: reachable_induct) case init thus ?case by simp next case (hash t r s m) let ?t' = "t @ [Learns {Hash m}]" note IH = hash(2) have "m' \ knows t \ m' = Hash m" (is "?old \ ?new") using hash by fastforce moreover { assume "?new" hence ?case using `m \ knows t` by fastforce } moreover { assume "?old" hence ?case by (fastforce intro!: IH cases_appendI_trace) } ultimately show ?case by fast next case (encr t r s m k) let ?t' = "t @ [Learns {Enc m k}]" note IH = encr(2) have "m' \ knows t \ m' = Enc m k" (is "?old \ ?new") using encr by fastforce moreover { assume "?new" hence ?case using `m \ knows t` and `k \ knows t` by fastforce } moreover { assume "?old" hence ?case by (fast intro!: IH cases_appendI_trace) } ultimately show ?case by fast next case (tuple t r s x y) let ?t' = "t @ [Learns {Tup x y}]" note IH = tuple(2) have "m' \ knows t \ m' = Tup x y" (is "?old \ ?new") using tuple by fastforce moreover { assume "?new" hence ?case using `x \ knows t` and `y \ knows t` by fastforce } moreover { assume "?old" hence ?case by (fast intro!: IH cases_appendI_trace) } ultimately show ?case by fast next case (recv t r s i "done" l pt todo skipped) hence "?cases m' t r s" (is "?ik0 \ ?hash \ ?enc \ ?tup \ ?chain t r s \ ?note t r s \ ?keys") by clarsimp moreover { assume "?ik0" hence "?case" by blast } moreover { assume "?hash" hence "?case" by fastforce } moreover { assume "?enc" hence "?case" by fastforce } moreover { assume "?keys" hence "?case" by fastforce } moreover { assume "?tup" hence "?case" by fastforce } moreover { let ?t' = "t@[Step (i, Recv l pt)]" and ?r' = "r(i \ (done @ [Recv l pt], todo, skipped))" assume "?chain t r s" then obtain i' done' todo' l' pt' skipped' m where thread': "r i' = Some (done', todo', skipped')" and send: "Send l' pt' \ set done'" and msg: "Some m = inst s i' pt'" and chain:"decrChain [] t {St (i', Send l' pt')} m m'" by auto then interpret th1: reachable_thread P t r s i' done' todo' skipped' using recv by unfold_locales auto obtain done'' todo'' skipped'' where "Send l' pt' \ set done''" and "?r' i' = Some (done'', todo'', skipped'')" using `r i = Some (done, Recv l pt # todo, skipped)` thread' send by (cases "i = i'") (fastforce+) hence "?chain ?t' ?r' s" using chain msg by (fast intro!: decrChain_append) hence "?case" by auto } moreover { let ?t' = "t@[Step (i, Recv l pt)]" and ?r' = "r(i \ (done @ [Recv l pt], todo, skipped))" assume "?note t r s" then obtain i' done' todo' skipped' l' ty' pt' m where thread': "r i' = Some (done', todo', skipped')" and inDone: "Note l' ty' pt' \ set done'" and notSkipped: "Note l' ty' pt' \ skipped'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Note l' ty' pt')} m m'" by auto then interpret th1: reachable_thread P t r s i' done' todo' skipped' using recv by unfold_locales auto obtain done'' todo'' skipped'' where "Note l' ty' pt' \ set done''" and "Note l' ty' pt' \ skipped'' " and "?r' i' = Some (done'', todo'', skipped'')" using `r i = Some (done, Recv l pt # todo, skipped)` thread' inDone notSkipped by (cases "i = i'") (fastforce+) hence "?note ?t' ?r' s" using msg chain notSkipped inDone by (fast intro!: decrChain_append) hence "?case" by auto } ultimately show ?case by fastforce next case (send t r s i "done" l pt todo skipped m) then interpret th1: reachable_thread P t r s i "done" "Send l pt # todo" skipped by unfold_locales let ?r' = "r(i \ (done @ [Send l pt], todo, skipped))" let ?t' = "(t @ [Step (i, Send l pt)]) @ [Learns (pairParts m - knows t)]" have "m' \ knows t \ m' \ pairParts m \ m' \ knows t \ Some m = inst s i pt" (is "?old \ ?new") using send by fastforce moreover { assume "?new" hence "decrChain [] ?t' {St (i, Send l pt)} m m'" by (fastforce intro!: decrChain_unpair) moreover have "?r' i = Some (done @ [Send l pt], todo, skipped)" using th1.thread_exists by auto ultimately have ?case using `Some m = inst s i pt` apply- apply(rule disjI2) apply(rule disjI2) apply(rule disjI2) apply(rule disjI2) apply(rule disjI1) apply(fastforce) done } moreover { assume "?old" hence "?cases m' t r s" (is "?ik0 \ ?hash \ ?enc \ ?tup \ ?chain t r s \ ?note t r s \ ?keys") using send by clarsimp moreover { assume "?ik0" hence "?case" by blast } moreover { assume "?hash" hence "?case" by fastforce } moreover { assume "?enc" hence "?case" by fastforce } moreover { assume "?keys" hence "?case" by fastforce } moreover { assume "?tup" hence "?case" by fastforce } moreover { assume "?chain t r s" then obtain i' done' todo' l' pt' skipped' m where thread': "r i' = Some (done', todo',skipped')" and send: "Send l' pt' \ set done'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Send l' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Send l' pt' \ set done''" and "(r(i \ (done @ [Send l pt], todo, skipped))) i' = Some (done'', todo'',skipped'')" using `r i = Some (done, Send l pt # todo, skipped)` thread' send by (cases "i = i'") (fastforce+) hence "?chain ?t' ?r' s" using chain msg by (fast intro!: decrChain_append) hence "?case" by auto } moreover { assume "?note t r s" then obtain i' done' todo' skipped' l' ty' pt' m where thread': "r i' = Some (done', todo', skipped')" and inDone: "Note l' ty' pt' \ set done'" and notSkipped: "Note l' ty' pt' \ skipped'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Note l' ty' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Note l' ty' pt' \ set done''" and "Note l' ty' pt' \ skipped'' " and "?r' i' = Some (done'', todo'', skipped'')" using `r i = Some (done, Send l pt # todo, skipped)` thread' inDone notSkipped by (cases "i = i'") (fastforce+) hence "?note ?t' ?r' s" using chain notSkipped inDone msg by(fast intro!: decrChain_append) hence "?case" by auto } ultimately have ?case by fast } ultimately show ?case by fast next case (decr t r s m k) then interpret s1: reachable_state P t r s by unfold_locales let ?t' = "t @ [Learns (pairParts m - knows t)]" note IH = decr(2) have "m' \ knows t \ m' \ pairParts m \ m' \ knows t" (is "?old \ ?new") using decr by fastforce moreover { assume "?new" hence "m' \ pairParts m" and "m' \ knows t" by auto hence "(predOrd t (Ln m) (Ln (Enc m k)) \ predOrd t (Ln k) (Ln (Enc m k))) \ ((\i done todo skipped. r i = Some (done, todo,skipped) \ (\l pt ms. Send l pt \ set done \ Some ms = inst s i pt \ decrChain [] t {St (i, Send l pt)} ms (Enc m k)))) \ ((\i done todo skipped. r i = Some (done, todo,skipped) \ (\l ty pt ms. Note l ty pt \ set done \ Note l ty pt \ skipped \ Some ms = inst s i pt \ decrChain [] t {St (i, Note l ty pt)} ms (Enc m k))))" (is "?fake_enc \ ?decchain t (Enc m k) \ ?notechain t (Enc m k)") using IH[OF `Enc m k \ knows t`] by auto moreover { assume "?fake_enc" hence "?case" using `?new` by (auto dest!: in_knows_predOrd1 s1.rev_knows_pairParts_closedD) } moreover { assume "?decchain t (Enc m k)" then obtain i' done' todo' l' pt' skipped' ms where thread': "r i' = Some (done', todo',skipped')" and send: "Send l' pt' \ set done'" and msg: "Some ms = inst s i' pt'" and chain: "decrChain [] t {St (i', Send l' pt')} ms (Enc m k)" by auto moreover hence "decrChain [] ?t' {St (i', Send l' pt')} ms m'" using `?new` `Enc m k \ knows t` `inv k \ knows t` by (fastforce intro!: decrChain_decrypt) ultimately have "?decchain ?t' m'" by fastforce hence "?case" by blast } moreover { assume "?notechain t (Enc m k)" then obtain i' done' todo' l' ty' pt' skipped' ms where thread': "r i' = Some (done', todo',skipped')" and inDone: "Note l' ty' pt' \ set done'" and notSkipped: "Note l' ty' pt' \ skipped'" and msg: "Some ms = inst s i' pt'" and chain: "decrChain [] t {St (i', Note l' ty' pt')} ms (Enc m k)" by auto moreover hence "decrChain [] ?t' {St (i', Note l' ty' pt')} ms m'" using `?new` `Enc m k \ knows t` `inv k \ knows t` by (fastforce intro!: decrChain_decrypt) ultimately have "?notechain ?t' m'" by fastforce hence "?case" by blast } ultimately have ?case by fast } moreover { assume "?old" hence ?case by (fast intro!: IH cases_appendI_trace) } ultimately show ?case by fast thm decr next case(lkr t r s a) then interpret s1: reachable_state P t r s by unfold_locales let ?t' = "t @ [ LKReveal a, Learns (longTermKeys a - knows t)]" note IH = lkr(2) have "m' \ knows t \ m' \ longTermKeys a \ m' \ knows t" (is "?old \ ?new") using lkr by fastforce moreover { assume "?old" hence "?case" by (fast intro!: IH cases_appendI_trace) } moreover { assume "?new" hence ?case by (auto simp: longTermKeys_def) } ultimately show "?case" by fast next case (skip t r s i "done" l ty pt todo skipped) then interpret this_thread: reachable_thread P t r s i "done" "Note l ty pt # todo" skipped by unfold_locales let ?r' = "r(i \ (done @ [Note l ty pt], todo, insert (Note l ty pt) skipped))" have "m' \ knows t" using skip by fastforce hence "?cases m' t r s" (is "?ik0 \ ?hash \ ?enc \ ?tup \ ?chain t r s \ ?note t r s \ ?keys") using skip by clarsimp moreover { assume "?ik0" hence "?case" by blast } moreover { assume "?hash" hence "?case" by fastforce } moreover { assume "?enc" hence "?case" by fastforce } moreover { assume "?keys" hence "?case" by fastforce } moreover { assume "?tup" hence "?case" by fastforce } moreover { assume "?chain t r s" then obtain i' done' todo' l' pt' skipped' m where thread': "r i' = Some (done', todo',skipped')" and send: "Send l' pt' \ set done'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Send l' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Send l' pt' \ set done''" and "?r' i' = Some (done'', todo'',skipped'')" using skip(3) thread' send by (cases "i = i'") (fastforce+) hence "?chain t ?r' s" using chain msg by fast hence "?case" by auto } moreover { assume "?note t r s" then obtain i' done' todo' skipped' l' ty' pt' m where thread': "r i' = Some (done', todo', skipped')" and inDone: "Note l' ty' pt' \ set done'" and notSkipped: "Note l' ty' pt' \ skipped'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Note l' ty' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Note l' ty' pt' \ set done''" and "Note l' ty' pt' \ skipped'' " and "?r' i' = Some (done'', todo'', skipped'')" using `r i = Some (done, Note l ty pt # todo, skipped)` thread' inDone notSkipped by (cases "i = i'") (force dest: this_thread.done_notin_todoD)+ hence "?note t ?r' s" using chain notSkipped inDone msg by fast hence "?case" by auto } moreover { assume "?keys" hence "?case" by fastforce } ultimately show "?case" by fastforce next case(compr t r s i "done" l ty pt todo skipped m m') then interpret th1: reachable_thread P t r s i "done" "Note l ty pt # todo" skipped by unfold_locales let ?r' = "r(i \ (done @ [Note l ty pt], todo, skipped))" let ?t' = "(t @ [Step (i, Note l ty pt)]) @ [Learns (pairParts m - knows t)]" have "m' \ knows t \ m' \ pairParts m \ m' \ knows t \ Some m = inst s i pt" (is "?old \ ?new") using compr by fastforce moreover { assume "?new" (* hence "m' \ pairParts (inst s i pt)" and "m' \ knows t" using `m = inst s i pt` by auto *) hence "decrChain [] ?t' {St (i, Note l ty pt)} m m'" by (fastforce intro!: decrChain_unpair) moreover have "?r' i = Some (done @ [Note l ty pt], todo, skipped)" using th1.thread_exists by auto moreover have "Note l ty pt \ set (Note l ty pt # todo)" using th1.thread_exists by auto hence "Note l ty pt \ skipped" by (fastforce dest: th1.todo_notin_skippedD) ultimately have ?case using `Some m = inst s i pt` apply- apply(rule disjI2) apply(rule disjI2) apply(rule disjI2) apply(rule disjI2) apply(rule disjI2) apply(rule disjI1) by force } moreover { assume "?old" hence "?cases m' t r s" (is "?ik0 \ ?hash \ ?enc \ ?tup \ ?chain t r s \ ?note t r s \ ?keys") using compr by clarsimp moreover { assume "?ik0" hence "?case" by blast } moreover { assume "?hash" hence "?case" by fastforce } moreover { assume "?enc" hence "?case" by fastforce } moreover { assume "?keys" hence "?case" by fastforce } moreover { assume "?tup" hence "?case" by fastforce } moreover { assume "?chain t r s" then obtain i' done' todo' l' pt' skipped' m where thread': "r i' = Some (done', todo',skipped')" and send: "Send l' pt' \ set done'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Send l' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Send l' pt' \ set done''" and "(r(i \ (done @ [Note l ty pt], todo, skipped))) i' = Some (done'', todo'',skipped'')" using compr(3) thread' send by (cases "i = i'") (fastforce+) hence "?chain ?t' ?r' s" using chain msg by(fast intro!: decrChain_append) hence "?case" by auto } moreover { assume "?note t r s" then obtain i' done' todo' skipped' l' ty' pt' m where thread': "r i' = Some (done', todo', skipped')" and inDone: "Note l' ty' pt' \ set done'" and notSkipped: "Note l' ty' pt' \ skipped'" and msg: "Some m = inst s i' pt'" and chain: "decrChain [] t {St (i', Note l' ty' pt')} m m'" by auto obtain done'' todo'' skipped'' where "Note l' ty' pt' \ set done''" and "Note l' ty' pt' \ skipped'' " and "?r' i' = Some (done'', todo'', skipped'')" using `r i = Some (done, Note l ty pt # todo, skipped)` thread' inDone notSkipped by (cases "i = i'") (fastforce+) hence "?note ?t' ?r' s" using chain notSkipped inDone msg by(fast intro!: decrChain_append) hence "?case" by auto } ultimately have ?case by fast } ultimately show ?case by fast qed qed end