(* Title: HOL/Auth/KerberosIV ID: $Id: KerberosIV_Gets.thy,v 1.4 2007/07/11 09:15:16 berghofe Exp $ Author: Giampaolo Bella, Cambridge University Computer Laboratory Copyright 1998 University of Cambridge *) header{*The Kerberos Protocol, Version IV*} theory KerberosIV_Gets imports Public begin text{*The "u" prefix indicates theorems referring to an updated version of the protocol. The "r" suffix indicates theorems where the confidentiality assumptions are relaxed by the corresponding arguments.*} abbreviation Kas :: agent where "Kas == Server" abbreviation Tgs :: agent where "Tgs == Friend 0" axioms Tgs_not_bad [iff]: "Tgs ∉ bad" --{*Tgs is secure --- we already know that Kas is secure*} constdefs (* authKeys are those contained in an authTicket *) authKeys :: "event list => key set" "authKeys evs == {authK. ∃A Peer Ta. Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Peer, Number Ta, (Crypt (shrK Peer) \<lbrace>Agent A, Agent Peer, Key authK, Number Ta\<rbrace>) \<rbrace>) ∈ set evs}" (* States than an event really appears only once on a trace *) Unique :: "[event, event list] => bool" ("Unique _ on _") "Unique ev on evs == ev ∉ set (tl (dropWhile (% z. z ≠ ev) evs))" consts (*Duration of the authentication key*) authKlife :: nat (*Duration of the service key*) servKlife :: nat (*Duration of an authenticator*) authlife :: nat (*Upper bound on the time of reaction of a server*) replylife :: nat specification (authKlife) authKlife_LB [iff]: "2 ≤ authKlife" by blast specification (servKlife) servKlife_LB [iff]: "2 + authKlife ≤ servKlife" by blast specification (authlife) authlife_LB [iff]: "Suc 0 ≤ authlife" by blast specification (replylife) replylife_LB [iff]: "Suc 0 ≤ replylife" by blast abbreviation (*The current time is just the length of the trace!*) CT :: "event list=>nat" where "CT == length" abbreviation expiredAK :: "[nat, event list] => bool" where "expiredAK Ta evs == authKlife + Ta < CT evs" abbreviation expiredSK :: "[nat, event list] => bool" where "expiredSK Ts evs == servKlife + Ts < CT evs" abbreviation expiredA :: "[nat, event list] => bool" where "expiredA T evs == authlife + T < CT evs" abbreviation valid :: "[nat, nat] => bool" ("valid _ wrt _") where "valid T1 wrt T2 == T1 <= replylife + T2" (*---------------------------------------------------------------------*) (* Predicate formalising the association between authKeys and servKeys *) constdefs AKcryptSK :: "[key, key, event list] => bool" "AKcryptSK authK servK evs == ∃A B Ts. Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> \<rbrace>) ∈ set evs" inductive_set "kerbIV_gets" :: "event list set" where Nil: "[] ∈ kerbIV_gets" | Fake: "[| evsf ∈ kerbIV_gets; X ∈ synth (analz (spies evsf)) |] ==> Says Spy B X # evsf ∈ kerbIV_gets" | Reception: "[| evsr ∈ kerbIV_gets; Says A B X ∈ set evsr |] ==> Gets B X # evsr ∈ kerbIV_gets" (* FROM the initiator *) | K1: "[| evs1 ∈ kerbIV_gets |] ==> Says A Kas \<lbrace>Agent A, Agent Tgs, Number (CT evs1)\<rbrace> # evs1 ∈ kerbIV_gets" (* Adding the timestamp serves to A in K3 to check that she doesn't get a reply too late. This kind of timeouts are ordinary. If a server's reply is late, then it is likely to be fake. *) (*---------------------------------------------------------------------*) (*FROM Kas *) | K2: "[| evs2 ∈ kerbIV_gets; Key authK ∉ used evs2; authK ∈ symKeys; Gets Kas \<lbrace>Agent A, Agent Tgs, Number T1\<rbrace> ∈ set evs2 |] ==> Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number (CT evs2), (Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number (CT evs2)\<rbrace>)\<rbrace>) # evs2 ∈ kerbIV_gets" (* The internal encryption builds the authTicket. The timestamp doesn't change inside the two encryptions: the external copy will be used by the initiator in K3; the one inside the authTicket by Tgs in K4. *) (*---------------------------------------------------------------------*) (* FROM the initiator *) | K3: "[| evs3 ∈ kerbIV_gets; Says A Kas \<lbrace>Agent A, Agent Tgs, Number T1\<rbrace> ∈ set evs3; Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs3; valid Ta wrt T1 |] ==> Says A Tgs \<lbrace>authTicket, (Crypt authK \<lbrace>Agent A, Number (CT evs3)\<rbrace>), Agent B\<rbrace> # evs3 ∈ kerbIV_gets" (*The two events amongst the premises allow A to accept only those authKeys that are not issued late. *) (*---------------------------------------------------------------------*) (* FROM Tgs *) (* Note that the last temporal check is not mentioned in the original MIT specification. Adding it makes many goals "available" to the peers. Theorems that exploit it have the suffix `_u', which stands for updated protocol. *) | K4: "[| evs4 ∈ kerbIV_gets; Key servK ∉ used evs4; servK ∈ symKeys; B ≠ Tgs; authK ∈ symKeys; Gets Tgs \<lbrace> (Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>), (Crypt authK \<lbrace>Agent A, Number T2\<rbrace>), Agent B\<rbrace> ∈ set evs4; ¬ expiredAK Ta evs4; ¬ expiredA T2 evs4; servKlife + (CT evs4) <= authKlife + Ta |] ==> Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number (CT evs4), Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number (CT evs4)\<rbrace> \<rbrace>) # evs4 ∈ kerbIV_gets" (* Tgs creates a new session key per each request for a service, without checking if there is still a fresh one for that service. The cipher under Tgs' key is the authTicket, the cipher under B's key is the servTicket, which is built now. NOTE that the last temporal check is not present in the MIT specification. *) (*---------------------------------------------------------------------*) (* FROM the initiator *) | K5: "[| evs5 ∈ kerbIV_gets; authK ∈ symKeys; servK ∈ symKeys; Says A Tgs \<lbrace>authTicket, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B\<rbrace> ∈ set evs5; Gets A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs5; valid Ts wrt T2 |] ==> Says A B \<lbrace>servTicket, Crypt servK \<lbrace>Agent A, Number (CT evs5)\<rbrace> \<rbrace> # evs5 ∈ kerbIV_gets" (* Checks similar to those in K3. *) (*---------------------------------------------------------------------*) (* FROM the responder*) | K6: "[| evs6 ∈ kerbIV_gets; Gets B \<lbrace> (Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>), (Crypt servK \<lbrace>Agent A, Number T3\<rbrace>)\<rbrace> ∈ set evs6; ¬ expiredSK Ts evs6; ¬ expiredA T3 evs6 |] ==> Says B A (Crypt servK (Number T3)) # evs6 ∈ kerbIV_gets" (* Checks similar to those in K4. *) (*---------------------------------------------------------------------*) (* Leaking an authK... *) | Oops1: "[| evsO1 ∈ kerbIV_gets; A ≠ Spy; Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evsO1; expiredAK Ta evsO1 |] ==> Says A Spy \<lbrace>Agent A, Agent Tgs, Number Ta, Key authK\<rbrace> # evsO1 ∈ kerbIV_gets" (*---------------------------------------------------------------------*) (*Leaking a servK... *) | Oops2: "[| evsO2 ∈ kerbIV_gets; A ≠ Spy; Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evsO2; expiredSK Ts evsO2 |] ==> Says A Spy \<lbrace>Agent A, Agent B, Number Ts, Key servK\<rbrace> # evsO2 ∈ kerbIV_gets" (*---------------------------------------------------------------------*) declare Says_imp_knows_Spy [THEN parts.Inj, dest] declare parts.Body [dest] declare analz_into_parts [dest] declare Fake_parts_insert_in_Un [dest] subsection{*Lemmas about reception event*} lemma Gets_imp_Says : "[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> ∃A. Says A B X ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto done lemma Gets_imp_knows_Spy: "[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> X ∈ knows Spy evs" apply (blast dest!: Gets_imp_Says Says_imp_knows_Spy) done (*Needed for force to work for example in new_keys_not_used*) declare Gets_imp_knows_Spy [THEN parts.Inj, dest] lemma Gets_imp_knows: "[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> X ∈ knows B evs" apply (case_tac "B = Spy") apply (blast dest!: Gets_imp_knows_Spy) apply (blast dest!: Gets_imp_knows_agents) done subsection{*Lemmas about @{term authKeys}*} lemma authKeys_empty: "authKeys [] = {}" apply (unfold authKeys_def) apply (simp (no_asm)) done lemma authKeys_not_insert: "(∀A Ta akey Peer. ev ≠ Says Kas A (Crypt (shrK A) \<lbrace>akey, Agent Peer, Ta, (Crypt (shrK Peer) \<lbrace>Agent A, Agent Peer, akey, Ta\<rbrace>)\<rbrace>)) ==> authKeys (ev # evs) = authKeys evs" by (unfold authKeys_def, auto) lemma authKeys_insert: "authKeys (Says Kas A (Crypt (shrK A) \<lbrace>Key K, Agent Peer, Number Ta, (Crypt (shrK Peer) \<lbrace>Agent A, Agent Peer, Key K, Number Ta\<rbrace>)\<rbrace>) # evs) = insert K (authKeys evs)" by (unfold authKeys_def, auto) lemma authKeys_simp: "K ∈ authKeys (Says Kas A (Crypt (shrK A) \<lbrace>Key K', Agent Peer, Number Ta, (Crypt (shrK Peer) \<lbrace>Agent A, Agent Peer, Key K', Number Ta\<rbrace>)\<rbrace>) # evs) ==> K = K' | K ∈ authKeys evs" by (unfold authKeys_def, auto) lemma authKeysI: "Says Kas A (Crypt (shrK A) \<lbrace>Key K, Agent Tgs, Number Ta, (Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key K, Number Ta\<rbrace>)\<rbrace>) ∈ set evs ==> K ∈ authKeys evs" by (unfold authKeys_def, auto) lemma authKeys_used: "K ∈ authKeys evs ==> Key K ∈ used evs" by (simp add: authKeys_def, blast) subsection{*Forwarding Lemmas*} lemma Says_ticket_parts: "Says S A (Crypt K \<lbrace>SesKey, B, TimeStamp, Ticket\<rbrace>) ∈ set evs ==> Ticket ∈ parts (spies evs)" apply blast done lemma Gets_ticket_parts: "[|Gets A (Crypt K \<lbrace>SesKey, Peer, Ta, Ticket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> Ticket ∈ parts (spies evs)" apply (blast dest: Gets_imp_knows_Spy [THEN parts.Inj]) done lemma Oops_range_spies1: "[| Says Kas A (Crypt KeyA \<lbrace>Key authK, Peer, Ta, authTicket\<rbrace>) ∈ set evs ; evs ∈ kerbIV_gets |] ==> authK ∉ range shrK & authK ∈ symKeys" apply (erule rev_mp) apply (erule kerbIV_gets.induct, auto) done lemma Oops_range_spies2: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Ts, servTicket\<rbrace>) ∈ set evs ; evs ∈ kerbIV_gets |] ==> servK ∉ range shrK & servK ∈ symKeys" apply (erule rev_mp) apply (erule kerbIV_gets.induct, auto) done (*Spy never sees another agent's shared key! (unless it's lost at start)*) lemma Spy_see_shrK [simp]: "evs ∈ kerbIV_gets ==> (Key (shrK A) ∈ parts (spies evs)) = (A ∈ bad)" apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) apply (blast+) done lemma Spy_analz_shrK [simp]: "evs ∈ kerbIV_gets ==> (Key (shrK A) ∈ analz (spies evs)) = (A ∈ bad)" by auto lemma Spy_see_shrK_D [dest!]: "[| Key (shrK A) ∈ parts (spies evs); evs ∈ kerbIV_gets |] ==> A:bad" by (blast dest: Spy_see_shrK) lemmas Spy_analz_shrK_D = analz_subset_parts [THEN subsetD, THEN Spy_see_shrK_D, dest!] text{*Nobody can have used non-existent keys!*} lemma new_keys_not_used [simp]: "[|Key K ∉ used evs; K ∈ symKeys; evs ∈ kerbIV_gets|] ==> K ∉ keysFor (parts (spies evs))" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake*} apply (force dest!: keysFor_parts_insert) txt{*Others*} apply (force dest!: analz_shrK_Decrypt)+ done (*Earlier, all protocol proofs declared this theorem. But few of them actually need it! (Another is Yahalom) *) lemma new_keys_not_analzd: "[|evs ∈ kerbIV_gets; K ∈ symKeys; Key K ∉ used evs|] ==> K ∉ keysFor (analz (spies evs))" by (blast dest: new_keys_not_used intro: keysFor_mono [THEN subsetD]) subsection{*Regularity Lemmas*} text{*These concern the form of items passed in messages*} text{*Describes the form of all components sent by Kas*} lemma Says_Kas_message_form: "[| Says Kas A (Crypt K \<lbrace>Key authK, Agent Peer, Number Ta, authTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> K = shrK A & Peer = Tgs & authK ∉ range shrK & authK ∈ authKeys evs & authK ∈ symKeys & authTicket = (Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>)" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (simp_all (no_asm) add: authKeys_def authKeys_insert) apply blast+ done lemma SesKey_is_session_key: "[| Crypt (shrK Tgs_B) \<lbrace>Agent A, Agent Tgs_B, Key SesKey, Number T\<rbrace> ∈ parts (spies evs); Tgs_B ∉ bad; evs ∈ kerbIV_gets |] ==> SesKey ∉ range shrK" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast) done lemma authTicket_authentic: "[| Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace> ∈ parts (spies evs); evs ∈ kerbIV_gets |] ==> Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake, K4*} apply (blast+) done lemma authTicket_crypt_authK: "[| Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace> ∈ parts (spies evs); evs ∈ kerbIV_gets |] ==> authK ∈ authKeys evs" apply (frule authTicket_authentic, assumption) apply (simp (no_asm) add: authKeys_def) apply blast done lemma Says_Tgs_message_form: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> B ≠ Tgs & authK ∉ range shrK & authK ∈ authKeys evs & authK ∈ symKeys & servK ∉ range shrK & servK ∉ authKeys evs & servK ∈ symKeys & servTicket = (Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>)" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (simp_all add: authKeys_insert authKeys_not_insert authKeys_empty authKeys_simp, blast, auto) txt{*Three subcases of Message 4*} apply (blast dest!: SesKey_is_session_key) apply (blast dest: authTicket_crypt_authK) apply (blast dest!: authKeys_used Says_Kas_message_form) done lemma authTicket_form: "[| Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Ta, authTicket\<rbrace> ∈ parts (spies evs); A ∉ bad; evs ∈ kerbIV_gets |] ==> authK ∉ range shrK & authK ∈ symKeys & authTicket = Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Ta\<rbrace>" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) apply blast+ done text{* This form holds also over an authTicket, but is not needed below.*} lemma servTicket_form: "[| Crypt authK \<lbrace>Key servK, Agent B, Ts, servTicket\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); evs ∈ kerbIV_gets |] ==> servK ∉ range shrK & servK ∈ symKeys & (∃A. servTicket = Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Ts\<rbrace>)" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast) done text{* Essentially the same as @{text authTicket_form} *} lemma Says_kas_message_form: "[| Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Ta, authTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> authK ∉ range shrK & authK ∈ symKeys & authTicket = Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Ta\<rbrace> | authTicket ∈ analz (spies evs)" by (blast dest: analz_shrK_Decrypt authTicket_form Gets_imp_knows_Spy [THEN analz.Inj]) lemma Says_tgs_message_form: "[| Gets A (Crypt authK \<lbrace>Key servK, Agent B, Ts, servTicket\<rbrace>) ∈ set evs; authK ∈ symKeys; evs ∈ kerbIV_gets |] ==> servK ∉ range shrK & (∃A. servTicket = Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Ts\<rbrace>) | servTicket ∈ analz (spies evs)" apply (frule Gets_imp_knows_Spy [THEN analz.Inj], auto) apply (force dest!: servTicket_form) apply (frule analz_into_parts) apply (frule servTicket_form, auto) done subsection{*Authenticity theorems: confirm origin of sensitive messages*} lemma authK_authentic: "[| Crypt (shrK A) \<lbrace>Key authK, Peer, Ta, authTicket\<rbrace> ∈ parts (spies evs); A ∉ bad; evs ∈ kerbIV_gets |] ==> Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Peer, Ta, authTicket\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake*} apply blast txt{*K4*} apply (blast dest!: authTicket_authentic [THEN Says_Kas_message_form]) done text{*If a certain encrypted message appears then it originated with Tgs*} lemma servK_authentic: "[| Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); authK ∉ range shrK; evs ∈ kerbIV_gets |] ==> ∃A. Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake*} apply blast txt{*K2*} apply blast txt{*K4*} apply auto done lemma servK_authentic_bis: "[| Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); B ≠ Tgs; evs ∈ kerbIV_gets |] ==> ∃A. Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake*} apply blast txt{*K4*} apply blast done text{*Authenticity of servK for B*} lemma servTicket_authentic_Tgs: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃authK. Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) apply blast+ done text{*Anticipated here from next subsection*} lemma K4_imp_K2: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets|] ==> ∃Ta. Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, auto) apply (blast dest!: Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Fst, THEN authTicket_authentic]) done text{*Anticipated here from next subsection*} lemma u_K4_imp_K2: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets|] ==> ∃Ta. (Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs & servKlife + Ts <= authKlife + Ta)" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, auto) apply (blast dest!: Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Fst, THEN authTicket_authentic]) done lemma servTicket_authentic_Kas: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃authK Ta. Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs" apply (blast dest!: servTicket_authentic_Tgs K4_imp_K2) done lemma u_servTicket_authentic_Kas: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃authK Ta. Says Kas A (Crypt(shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs & servKlife + Ts <= authKlife + Ta" apply (blast dest!: servTicket_authentic_Tgs u_K4_imp_K2) done lemma servTicket_authentic: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃Ta authK. Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs & Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>\<rbrace>) ∈ set evs" apply (blast dest: servTicket_authentic_Tgs K4_imp_K2) done lemma u_servTicket_authentic: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃Ta authK. (Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs & Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>\<rbrace>) ∈ set evs & servKlife + Ts <= authKlife + Ta)" apply (blast dest: servTicket_authentic_Tgs u_K4_imp_K2) done lemma u_NotexpiredSK_NotexpiredAK: "[| ¬ expiredSK Ts evs; servKlife + Ts <= authKlife + Ta |] ==> ¬ expiredAK Ta evs" apply (blast dest: leI le_trans dest: leD) done subsection{* Reliability: friendly agents send something if something else happened*} lemma K3_imp_K2: "[| Says A Tgs \<lbrace>authTicket, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B\<rbrace> ∈ set evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> ∃Ta. Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast, blast) apply (blast dest: Gets_imp_knows_Spy [THEN parts.Inj, THEN authK_authentic]) done text{*Anticipated here from next subsection. An authK is encrypted by one and only one Shared key. A servK is encrypted by one and only one authK.*} lemma Key_unique_SesKey: "[| Crypt K \<lbrace>Key SesKey, Agent B, T, Ticket\<rbrace> ∈ parts (spies evs); Crypt K' \<lbrace>Key SesKey, Agent B', T', Ticket'\<rbrace> ∈ parts (spies evs); Key SesKey ∉ analz (spies evs); evs ∈ kerbIV_gets |] ==> K=K' & B=B' & T=T' & Ticket=Ticket'" apply (erule rev_mp) apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake, K2, K4*} apply (blast+) done lemma Tgs_authenticates_A: "[| Crypt authK \<lbrace>Agent A, Number T2\<rbrace> ∈ parts (spies evs); Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); A ∉ bad; evs ∈ kerbIV_gets |] ==> ∃ B. Says A Tgs \<lbrace> Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B \<rbrace> ∈ set evs" apply (drule authTicket_authentic, assumption, rotate_tac 4) apply (erule rev_mp, erule rev_mp, erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [6] Gets_ticket_parts) apply (frule_tac [9] Gets_ticket_parts) apply (simp_all (no_asm_simp) add: all_conj_distrib) txt{*Fake*} apply blast txt{*K2*} apply (force dest!: Crypt_imp_keysFor) txt{*K3*} apply (blast dest: Key_unique_SesKey) txt{*K5*} txt{*If authKa were compromised, so would be authK*} apply (case_tac "Key authKa ∈ analz (spies evs5)") apply (force dest!: Gets_imp_knows_Spy [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) txt{*Besides, since authKa originated with Kas anyway...*} apply (clarify, drule K3_imp_K2, assumption, assumption) apply (clarify, drule Says_Kas_message_form, assumption) txt{*...it cannot be a shared key*. Therefore @{term servK_authentic} applies. Contradition: Tgs used authK as a servkey, while Kas used it as an authkey*} apply (blast dest: servK_authentic Says_Tgs_message_form) done lemma Says_K5: "[| Crypt servK \<lbrace>Agent A, Number T3\<rbrace> ∈ parts (spies evs); Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; Key servK ∉ analz (spies evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Says A B \<lbrace>servTicket, Crypt servK \<lbrace>Agent A, Number T3\<rbrace>\<rbrace> ∈ set evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [6] Gets_ticket_parts) apply (frule_tac [9] Gets_ticket_parts) apply (simp_all (no_asm_simp) add: all_conj_distrib) apply blast txt{*K3*} apply (blast dest: authK_authentic Says_Kas_message_form Says_Tgs_message_form) txt{*K4*} apply (force dest!: Crypt_imp_keysFor) txt{*K5*} apply (blast dest: Key_unique_SesKey) done text{*Anticipated here from next subsection*} lemma unique_CryptKey: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key SesKey, T\<rbrace> ∈ parts (spies evs); Crypt (shrK B') \<lbrace>Agent A', Agent B', Key SesKey, T'\<rbrace> ∈ parts (spies evs); Key SesKey ∉ analz (spies evs); evs ∈ kerbIV_gets |] ==> A=A' & B=B' & T=T'" apply (erule rev_mp) apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake, K2, K4*} apply (blast+) done lemma Says_K6: "[| Crypt servK (Number T3) ∈ parts (spies evs); Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; Key servK ∉ analz (spies evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Says B A (Crypt servK (Number T3)) ∈ set evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts) apply (simp_all (no_asm_simp)) apply blast apply (force dest!: Crypt_imp_keysFor, clarify) apply (frule Says_Tgs_message_form, assumption, clarify) (*PROOF FAILED if omitted*) apply (blast dest: unique_CryptKey) done text{*Needs a unicity theorem, hence moved here*} lemma servK_authentic_ter: "[| Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs; Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); evs ∈ kerbIV_gets |] ==> Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs" apply (frule Says_Kas_message_form, assumption) apply (erule rev_mp) apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast) txt{*K2 and K4 remain*} prefer 2 apply (blast dest!: unique_CryptKey) apply (blast dest!: servK_authentic Says_Tgs_message_form authKeys_used) done subsection{*Unicity Theorems*} text{* The session key, if secure, uniquely identifies the Ticket whether authTicket or servTicket. As a matter of fact, one can read also Tgs in the place of B. *} lemma unique_authKeys: "[| Says Kas A (Crypt Ka \<lbrace>Key authK, Agent Tgs, Ta, X\<rbrace>) ∈ set evs; Says Kas A' (Crypt Ka' \<lbrace>Key authK, Agent Tgs, Ta', X'\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> A=A' & Ka=Ka' & Ta=Ta' & X=X'" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*K2*} apply blast done text{* servK uniquely identifies the message from Tgs *} lemma unique_servKeys: "[| Says Tgs A (Crypt K \<lbrace>Key servK, Agent B, Ts, X\<rbrace>) ∈ set evs; Says Tgs A' (Crypt K' \<lbrace>Key servK, Agent B', Ts', X'\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> A=A' & B=B' & K=K' & Ts=Ts' & X=X'" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*K4*} apply blast done text{* Revised unicity theorems *} lemma Kas_Unique: "[| Says Kas A (Crypt Ka \<lbrace>Key authK, Agent Tgs, Ta, authTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> Unique (Says Kas A (Crypt Ka \<lbrace>Key authK, Agent Tgs, Ta, authTicket\<rbrace>)) on evs" apply (erule rev_mp, erule kerbIV_gets.induct, simp_all add: Unique_def) apply blast done lemma Tgs_Unique: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Ts, servTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> Unique (Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Ts, servTicket\<rbrace>)) on evs" apply (erule rev_mp, erule kerbIV_gets.induct, simp_all add: Unique_def) apply blast done subsection{*Lemmas About the Predicate @{term AKcryptSK}*} lemma not_AKcryptSK_Nil [iff]: "¬ AKcryptSK authK servK []" by (simp add: AKcryptSK_def) lemma AKcryptSKI: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, X \<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> AKcryptSK authK servK evs" apply (unfold AKcryptSK_def) apply (blast dest: Says_Tgs_message_form) done lemma AKcryptSK_Says [simp]: "AKcryptSK authK servK (Says S A X # evs) = (Tgs = S & (∃B Ts. X = Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> \<rbrace>) | AKcryptSK authK servK evs)" apply (unfold AKcryptSK_def) apply (simp (no_asm)) apply blast done (*A fresh authK cannot be associated with any other (with respect to a given trace). *) lemma Auth_fresh_not_AKcryptSK: "[| Key authK ∉ used evs; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK authK servK evs" apply (unfold AKcryptSK_def) apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast) done (*A fresh servK cannot be associated with any other (with respect to a given trace). *) lemma Serv_fresh_not_AKcryptSK: "Key servK ∉ used evs ==> ¬ AKcryptSK authK servK evs" apply (unfold AKcryptSK_def, blast) done lemma authK_not_AKcryptSK: "[| Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, tk\<rbrace> ∈ parts (spies evs); evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK K authK evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) txt{*Fake*} apply blast txt{*Reception*} apply (simp add: AKcryptSK_def) txt{*K2: by freshness*} apply (simp add: AKcryptSK_def) txt{*K4*} apply (blast+) done text{*A secure serverkey cannot have been used to encrypt others*} lemma servK_not_AKcryptSK: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key SK, Number Ts\<rbrace> ∈ parts (spies evs); Key SK ∉ analz (spies evs); SK ∈ symKeys; B ≠ Tgs; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK SK K evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all, blast) txt{*Reception*} apply (simp add: AKcryptSK_def) txt{*K4 splits into distinct subcases*} apply auto txt{*servK can't have been enclosed in two certificates*} prefer 2 apply (blast dest: unique_CryptKey) txt{*servK is fresh and so could not have been used, by @{text new_keys_not_used}*} apply (force dest!: Crypt_imp_invKey_keysFor simp add: AKcryptSK_def) done text{*Long term keys are not issued as servKeys*} lemma shrK_not_AKcryptSK: "evs ∈ kerbIV_gets ==> ¬ AKcryptSK K (shrK A) evs" apply (unfold AKcryptSK_def) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, auto) done text{*The Tgs message associates servK with authK and therefore not with any other key authK.*} lemma Says_Tgs_AKcryptSK: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, X \<rbrace>) ∈ set evs; authK' ≠ authK; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK authK' servK evs" apply (unfold AKcryptSK_def) apply (blast dest: unique_servKeys) done text{*Equivalently*} lemma not_different_AKcryptSK: "[| AKcryptSK authK servK evs; authK' ≠ authK; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK authK' servK evs ∧ servK ∈ symKeys" apply (simp add: AKcryptSK_def) apply (blast dest: unique_servKeys Says_Tgs_message_form) done lemma AKcryptSK_not_AKcryptSK: "[| AKcryptSK authK servK evs; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK servK K evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts) txt{*Reception*} prefer 3 apply (simp add: AKcryptSK_def) apply (simp_all, safe) txt{*K4 splits into subcases*} prefer 4 apply (blast dest!: authK_not_AKcryptSK) txt{*servK is fresh and so could not have been used, by @{text new_keys_not_used}*} prefer 2 apply (force dest!: Crypt_imp_invKey_keysFor simp add: AKcryptSK_def) txt{*Others by freshness*} apply (blast+) done text{*The only session keys that can be found with the help of session keys are those sent by Tgs in step K4. *} text{*We take some pains to express the property as a logical equivalence so that the simplifier can apply it.*} lemma Key_analz_image_Key_lemma: "P --> (Key K ∈ analz (Key`KK Un H)) --> (K:KK | Key K ∈ analz H) ==> P --> (Key K ∈ analz (Key`KK Un H)) = (K:KK | Key K ∈ analz H)" by (blast intro: analz_mono [THEN subsetD]) lemma AKcryptSK_analz_insert: "[| AKcryptSK K K' evs; K ∈ symKeys; evs ∈ kerbIV_gets |] ==> Key K' ∈ analz (insert (Key K) (spies evs))" apply (simp add: AKcryptSK_def, clarify) apply (drule Says_imp_spies [THEN analz.Inj, THEN analz_insertI], auto) done lemma authKeys_are_not_AKcryptSK: "[| K ∈ authKeys evs Un range shrK; evs ∈ kerbIV_gets |] ==> ∀SK. ¬ AKcryptSK SK K evs ∧ K ∈ symKeys" apply (simp add: authKeys_def AKcryptSK_def) apply (blast dest: Says_Kas_message_form Says_Tgs_message_form) done lemma not_authKeys_not_AKcryptSK: "[| K ∉ authKeys evs; K ∉ range shrK; evs ∈ kerbIV_gets |] ==> ∀SK. ¬ AKcryptSK K SK evs" apply (simp add: AKcryptSK_def) apply (blast dest: Says_Tgs_message_form) done subsection{*Secrecy Theorems*} text{*For the Oops2 case of the next theorem*} lemma Oops2_not_AKcryptSK: "[| evs ∈ kerbIV_gets; Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs |] ==> ¬ AKcryptSK servK SK evs" apply (blast dest: AKcryptSKI AKcryptSK_not_AKcryptSK) done text{* Big simplification law for keys SK that are not crypted by keys in KK It helps prove three, otherwise hard, facts about keys. These facts are exploited as simplification laws for analz, and also "limit the damage" in case of loss of a key to the spy. See ESORICS98. *} lemma Key_analz_image_Key [rule_format (no_asm)]: "evs ∈ kerbIV_gets ==> (∀SK KK. SK ∈ symKeys & KK <= -(range shrK) --> (∀K ∈ KK. ¬ AKcryptSK K SK evs) --> (Key SK ∈ analz (Key`KK Un (spies evs))) = (SK ∈ KK | Key SK ∈ analz (spies evs)))" apply (erule kerbIV_gets.induct) apply (frule_tac [11] Oops_range_spies2) apply (frule_tac [10] Oops_range_spies1) apply (frule_tac [8] Says_tgs_message_form) apply (frule_tac [6] Says_kas_message_form) apply (safe del: impI intro!: Key_analz_image_Key_lemma [THEN impI]) txt{*Case-splits for Oops1 and message 5: the negated case simplifies using the induction hypothesis*} apply (case_tac [12] "AKcryptSK authK SK evsO1") apply (case_tac [9] "AKcryptSK servK SK evs5") apply (simp_all del: image_insert add: analz_image_freshK_simps AKcryptSK_Says shrK_not_AKcryptSK Oops2_not_AKcryptSK Auth_fresh_not_AKcryptSK Serv_fresh_not_AKcryptSK Says_Tgs_AKcryptSK Spy_analz_shrK) --{*18 seconds on a 1.8GHz machine??*} txt{*Fake*} apply spy_analz txt{*Reception*} apply (simp add: AKcryptSK_def) txt{*K2*} apply blast txt{*K3*} apply blast txt{*K4*} apply (blast dest!: authK_not_AKcryptSK) txt{*K5*} apply (case_tac "Key servK ∈ analz (spies evs5) ") txt{*If servK is compromised then the result follows directly...*} apply (simp (no_asm_simp) add: analz_insert_eq Un_upper2 [THEN analz_mono, THEN subsetD]) txt{*...therefore servK is uncompromised.*} txt{*The AKcryptSK servK SK evs5 case leads to a contradiction.*} apply (blast elim!: servK_not_AKcryptSK [THEN [2] rev_notE] del: allE ballE) txt{*Another K5 case*} apply blast txt{*Oops1*} apply simp apply (blast dest!: AKcryptSK_analz_insert) done text{* First simplification law for analz: no session keys encrypt authentication keys or shared keys. *} lemma analz_insert_freshK1: "[| evs ∈ kerbIV_gets; K ∈ authKeys evs Un range shrK; SesKey ∉ range shrK |] ==> (Key K ∈ analz (insert (Key SesKey) (spies evs))) = (K = SesKey | Key K ∈ analz (spies evs))" apply (frule authKeys_are_not_AKcryptSK, assumption) apply (simp del: image_insert add: analz_image_freshK_simps add: Key_analz_image_Key) done text{* Second simplification law for analz: no service keys encrypt any other keys.*} lemma analz_insert_freshK2: "[| evs ∈ kerbIV_gets; servK ∉ (authKeys evs); servK ∉ range shrK; K ∈ symKeys |] ==> (Key K ∈ analz (insert (Key servK) (spies evs))) = (K = servK | Key K ∈ analz (spies evs))" apply (frule not_authKeys_not_AKcryptSK, assumption, assumption) apply (simp del: image_insert add: analz_image_freshK_simps add: Key_analz_image_Key) done text{* Third simplification law for analz: only one authentication key encrypts a certain service key.*} lemma analz_insert_freshK3: "[| AKcryptSK authK servK evs; authK' ≠ authK; authK' ∉ range shrK; evs ∈ kerbIV_gets |] ==> (Key servK ∈ analz (insert (Key authK') (spies evs))) = (servK = authK' | Key servK ∈ analz (spies evs))" apply (drule_tac authK' = authK' in not_different_AKcryptSK, blast, assumption) apply (simp del: image_insert add: analz_image_freshK_simps add: Key_analz_image_Key) done lemma analz_insert_freshK3_bis: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; authK ≠ authK'; authK' ∉ range shrK; evs ∈ kerbIV_gets |] ==> (Key servK ∈ analz (insert (Key authK') (spies evs))) = (servK = authK' | Key servK ∈ analz (spies evs))" apply (frule AKcryptSKI, assumption) apply (simp add: analz_insert_freshK3) done text{*a weakness of the protocol*} lemma authK_compromises_servK: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; authK ∈ symKeys; Key authK ∈ analz (spies evs); evs ∈ kerbIV_gets |] ==> Key servK ∈ analz (spies evs)" by (force dest: Says_imp_spies [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) lemma servK_notin_authKeysD: "[| Crypt authK \<lbrace>Key servK, Agent B, Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Ts\<rbrace>\<rbrace> ∈ parts (spies evs); Key servK ∉ analz (spies evs); B ≠ Tgs; evs ∈ kerbIV_gets |] ==> servK ∉ authKeys evs" apply (erule rev_mp) apply (erule rev_mp) apply (simp add: authKeys_def) apply (erule kerbIV_gets.induct, analz_mono_contra) apply (frule_tac [8] Gets_ticket_parts) apply (frule_tac [6] Gets_ticket_parts, simp_all) apply (blast+) done text{*If Spy sees the Authentication Key sent in msg K2, then the Key has expired.*} lemma Confidentiality_Kas_lemma [rule_format]: "[| authK ∈ symKeys; A ∉ bad; evs ∈ kerbIV_gets |] ==> Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs --> Key authK ∈ analz (spies evs) --> expiredAK Ta evs" apply (erule kerbIV_gets.induct) apply (frule_tac [11] Oops_range_spies2) apply (frule_tac [10] Oops_range_spies1) apply (frule_tac [8] Says_tgs_message_form) apply (frule_tac [6] Says_kas_message_form) apply (safe del: impI conjI impCE) apply (simp_all (no_asm_simp) add: Says_Kas_message_form less_SucI analz_insert_eq not_parts_not_analz analz_insert_freshK1 pushes) txt{*Fake*} apply spy_analz txt{*K2*} apply blast txt{*K4*} apply blast txt{*Level 8: K5*} apply (blast dest: servK_notin_authKeysD Says_Kas_message_form intro: less_SucI) txt{*Oops1*} apply (blast dest!: unique_authKeys intro: less_SucI) txt{*Oops2*} apply (blast dest: Says_Tgs_message_form Says_Kas_message_form) done lemma Confidentiality_Kas: "[| Says Kas A (Crypt Ka \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs; ¬ expiredAK Ta evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> Key authK ∉ analz (spies evs)" by (blast dest: Says_Kas_message_form Confidentiality_Kas_lemma) text{*If Spy sees the Service Key sent in msg K4, then the Key has expired.*} lemma Confidentiality_lemma [rule_format]: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>\<rbrace>) ∈ set evs; Key authK ∉ analz (spies evs); servK ∈ symKeys; A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Key servK ∈ analz (spies evs) --> expiredSK Ts evs" apply (erule rev_mp) apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply (rule_tac [10] impI)+; --{*The Oops1 case is unusual: must simplify @{term "Authkey ∉ analz (spies (ev#evs))"}, not letting @{text analz_mono_contra} weaken it to @{term "Authkey ∉ analz (spies evs)"}, for we then conclude @{term "authK ≠ authKa"}.*} apply analz_mono_contra apply (frule_tac [11] Oops_range_spies2) apply (frule_tac [10] Oops_range_spies1) apply (frule_tac [8] Says_tgs_message_form) apply (frule_tac [6] Says_kas_message_form) apply (safe del: impI conjI impCE) apply (simp_all add: less_SucI new_keys_not_analzd Says_Kas_message_form Says_Tgs_message_form analz_insert_eq not_parts_not_analz analz_insert_freshK1 analz_insert_freshK2 analz_insert_freshK3_bis pushes) txt{*Fake*} apply spy_analz txt{*K2*} apply (blast intro: parts_insertI less_SucI) txt{*K4*} apply (blast dest: authTicket_authentic Confidentiality_Kas) txt{*Oops2*} prefer 3 apply (blast dest: Says_imp_spies [THEN parts.Inj] Key_unique_SesKey intro: less_SucI) txt{*Oops1*} prefer 2 apply (blast dest: Says_Kas_message_form Says_Tgs_message_form intro: less_SucI) txt{*K5. Not clear how this step could be integrated with the main simplification step. Done in KerberosV.thy*} apply clarify apply (erule_tac V = "Says Aa Tgs ?X ∈ set ?evs" in thin_rl) apply (frule Gets_imp_knows_Spy [THEN parts.Inj, THEN servK_notin_authKeysD]) apply (assumption, assumption, blast, assumption) apply (simp add: analz_insert_freshK2) apply (blast dest: Says_imp_spies [THEN parts.Inj] Key_unique_SesKey intro: less_SucI) done text{* In the real world Tgs can't check wheter authK is secure! *} lemma Confidentiality_Tgs: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; Key authK ∉ analz (spies evs); ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Key servK ∉ analz (spies evs)" apply (blast dest: Says_Tgs_message_form Confidentiality_lemma) done text{* In the real world Tgs CAN check what Kas sends! *} lemma Confidentiality_Tgs_bis: "[| Says Kas A (Crypt Ka \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs; Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; ¬ expiredAK Ta evs; ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Key servK ∉ analz (spies evs)" apply (blast dest!: Confidentiality_Kas Confidentiality_Tgs) done text{*Most general form*} lemmas Confidentiality_Tgs_ter = authTicket_authentic [THEN Confidentiality_Tgs_bis] lemmas Confidentiality_Auth_A = authK_authentic [THEN Confidentiality_Kas] text{*Needs a confidentiality guarantee, hence moved here. Authenticity of servK for A*} lemma servK_authentic_bis_r: "[| Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace> ∈ parts (spies evs); Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); ¬ expiredAK Ta evs; A ∉ bad; evs ∈ kerbIV_gets |] ==>Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs" apply (blast dest: authK_authentic Confidentiality_Auth_A servK_authentic_ter) done lemma Confidentiality_Serv_A: "[| Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace> ∈ parts (spies evs); Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); ¬ expiredAK Ta evs; ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Key servK ∉ analz (spies evs)" apply (drule authK_authentic, assumption, assumption) apply (blast dest: Confidentiality_Kas Says_Kas_message_form servK_authentic_ter Confidentiality_Tgs_bis) done lemma Confidentiality_B: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace> ∈ parts (spies evs); ¬ expiredSK Ts evs; ¬ expiredAK Ta evs; A ∉ bad; B ∉ bad; B ≠ Tgs; evs ∈ kerbIV_gets |] ==> Key servK ∉ analz (spies evs)" apply (frule authK_authentic) apply (frule_tac [3] Confidentiality_Kas) apply (frule_tac [6] servTicket_authentic, auto) apply (blast dest!: Confidentiality_Tgs_bis dest: Says_Kas_message_form servK_authentic unique_servKeys unique_authKeys) done lemma u_Confidentiality_B: "[| Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace> ∈ parts (spies evs); ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad; B ≠ Tgs; evs ∈ kerbIV_gets |] ==> Key servK ∉ analz (spies evs)" apply (blast dest: u_servTicket_authentic u_NotexpiredSK_NotexpiredAK Confidentiality_Tgs_bis) done subsection{*2. Parties' strong authentication: non-injective agreement on the session key. The same guarantees also express key distribution, hence their names*} text{*Authentication here still is weak agreement - of B with A*} lemma A_authenticates_B: "[| Crypt servK (Number T3) ∈ parts (spies evs); Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace> ∈ parts (spies evs); Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace> ∈ parts (spies evs); Key authK ∉ analz (spies evs); Key servK ∉ analz (spies evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Says B A (Crypt servK (Number T3)) ∈ set evs" apply (frule authK_authentic) apply assumption+ apply (frule servK_authentic) prefer 2 apply (blast dest: authK_authentic Says_Kas_message_form) apply assumption+ apply (blast dest: K4_imp_K2 Key_unique_SesKey intro!: Says_K6) (*Single command proof: slower! apply (blast dest: authK_authentic servK_authentic Says_Kas_message_form Key_unique_SesKey K4_imp_K2 intro!: Says_K6) *) done (*These two have never been proved, because never were they needed before!*) lemma shrK_in_initState_Server[iff]: "Key (shrK A) ∈ initState Kas" by (induct_tac "A", auto) lemma shrK_in_knows_Server [iff]: "Key (shrK A) ∈ knows Kas evs" by (simp add: initState_subset_knows [THEN subsetD]) (*Because of our simple model of Tgs, the equivalent for it required an axiom*) lemma A_authenticates_and_keydist_to_Kas: "[| Gets A (Crypt (shrK A) \<lbrace>Key authK, Peer, Ta, authTicket\<rbrace>) ∈ set evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> Says Kas A (Crypt (shrK A) \<lbrace>Key authK, Peer, Ta, authTicket\<rbrace>) ∈ set evs ∧ Key authK ∈ analz(knows Kas evs)" apply (force dest!: authK_authentic Says_imp_knows [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) done lemma K3_imp_Gets: "[| Says A Tgs \<lbrace>Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B\<rbrace> ∈ set evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>\<rbrace>) ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto apply (blast dest: authTicket_form) done lemma Tgs_authenticates_and_keydist_to_A: "[| Gets Tgs \<lbrace> Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B \<rbrace> ∈ set evs; Key authK ∉ analz (spies evs); A ∉ bad; evs ∈ kerbIV_gets |] ==> ∃ B. Says A Tgs \<lbrace> Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B \<rbrace> ∈ set evs ∧ Key authK ∈ analz (knows A evs)" apply (frule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Fst], assumption) apply (drule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Snd, THEN parts.Fst], assumption) apply (drule Tgs_authenticates_A, assumption+, simp) apply (force dest!: K3_imp_Gets Gets_imp_knows [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) done lemma K4_imp_Gets: "[| Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; evs ∈ kerbIV_gets |] ==> ∃ Ta X. Gets Tgs \<lbrace>Crypt (shrK Tgs) \<lbrace>Agent A, Agent Tgs, Key authK, Number Ta\<rbrace>, X\<rbrace> ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto done lemma A_authenticates_and_keydist_to_Tgs: "[| Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs; Gets A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs; Key authK ∉ analz (spies evs); A ∉ bad; evs ∈ kerbIV_gets |] ==> Says Tgs A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs ∧ Key authK ∈ analz (knows Tgs evs) ∧ Key servK ∈ analz (knows Tgs evs)" apply (drule Gets_imp_knows_Spy [THEN parts.Inj], assumption) apply (drule Gets_imp_knows_Spy [THEN parts.Inj], assumption) apply (frule authK_authentic, assumption+) apply (drule servK_authentic_ter, assumption+) apply (frule K4_imp_Gets, assumption, erule exE, erule exE) apply (drule Gets_imp_knows [THEN analz.Inj, THEN analz.Fst, THEN analz.Decrypt, THEN analz.Snd, THEN analz.Snd, THEN analz.Fst], assumption, force) apply (frule Says_imp_knows [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) apply (force dest!: authK_authentic Says_Kas_message_form) apply simp done lemma K5_imp_Gets: "[| Says A B \<lbrace>servTicket, Crypt servK \<lbrace>Agent A, Number T3\<rbrace>\<rbrace> ∈ set evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> ∃ authK Ts authTicket T2. Gets A (Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>) ∈ set evs ∧ Says A Tgs \<lbrace>authTicket, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B\<rbrace> ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto done lemma K3_imp_Gets: "[| Says A Tgs \<lbrace>authTicket, Crypt authK \<lbrace>Agent A, Number T2\<rbrace>, Agent B\<rbrace> ∈ set evs; A ∉ bad; evs ∈ kerbIV_gets |] ==> ∃ Ta. Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs"; apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto done lemma B_authenticates_and_keydist_to_A: "[| Gets B \<lbrace>Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>, Crypt servK \<lbrace>Agent A, Number T3\<rbrace>\<rbrace> ∈ set evs; Key servK ∉ analz (spies evs); A ∉ bad; B ∉ bad; B ≠ Tgs; evs ∈ kerbIV_gets |] ==> Says A B \<lbrace>Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>, Crypt servK \<lbrace>Agent A, Number T3\<rbrace>\<rbrace> ∈ set evs ∧ Key servK ∈ analz (knows A evs)" apply (frule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Fst, THEN servTicket_authentic_Tgs], assumption+) apply (drule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Snd], assumption) apply (erule exE, drule Says_K5, assumption+) apply (frule K5_imp_Gets, assumption+) apply clarify apply (drule K3_imp_Gets, assumption+) apply (erule exE) apply (frule Gets_imp_knows_Spy [THEN parts.Inj, THEN authK_authentic, THEN Says_Kas_message_form], assumption+, clarify) apply (force dest!: Gets_imp_knows [THEN analz.Inj, THEN analz.Decrypt, THEN analz.Fst]) done lemma K6_imp_Gets: "[| Says B A (Crypt servK (Number T3)) ∈ set evs; B ∉ bad; evs ∈ kerbIV_gets |] ==> ∃ Ts X. Gets B \<lbrace>Crypt (shrK B) \<lbrace>Agent A, Agent B, Key servK, Number Ts\<rbrace>,X\<rbrace> ∈ set evs" apply (erule rev_mp) apply (erule kerbIV_gets.induct) apply auto done lemma A_authenticates_and_keydist_to_B: "[| Gets A \<lbrace>Crypt authK \<lbrace>Key servK, Agent B, Number Ts, servTicket\<rbrace>, Crypt servK (Number T3)\<rbrace> ∈ set evs; Gets A (Crypt (shrK A) \<lbrace>Key authK, Agent Tgs, Number Ta, authTicket\<rbrace>) ∈ set evs; Key authK ∉ analz (spies evs); Key servK ∉ analz (spies evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |] ==> Says B A (Crypt servK (Number T3)) ∈ set evs ∧ Key servK ∈ analz (knows B evs)" apply (frule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Fst], assumption) apply (drule Gets_imp_knows_Spy [THEN parts.Inj, THEN parts.Snd], assumption) apply (drule Gets_imp_knows_Spy [THEN parts.Inj], assumption) apply (drule A_authenticates_B, assumption+) apply (force dest!: K6_imp_Gets Gets_imp_knows [THEN analz.Inj, THEN analz.Fst, THEN analz.Decrypt, THEN analz.Snd, THEN analz.Snd, THEN analz.Fst]) done end
lemma Gets_imp_Says:
[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> ∃A. Says A B X ∈ set evs
lemma Gets_imp_knows_Spy:
[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> X ∈ knows Spy evs
lemma Gets_imp_knows:
[| Gets B X ∈ set evs; evs ∈ kerbIV_gets |] ==> X ∈ knows B evs
lemma authKeys_empty:
authKeys [] = {}
lemma authKeys_not_insert:
∀A Ta akey Peer.
ev ≠
Says Kas A
(Crypt (shrK A)
{|akey, Agent Peer, Ta,
Crypt (shrK Peer) {|Agent A, Agent Peer, akey, Ta|}|})
==> authKeys (ev # evs) = authKeys evs
lemma authKeys_insert:
authKeys
(Says Kas A
(Crypt (shrK A)
{|Key K, Agent Peer, Number Ta,
Crypt (shrK Peer) {|Agent A, Agent Peer, Key K, Number Ta|}|}) #
evs) =
insert K (authKeys evs)
lemma authKeys_simp:
K ∈ authKeys
(Says Kas A
(Crypt (shrK A)
{|Key K', Agent Peer, Number Ta,
Crypt (shrK Peer) {|Agent A, Agent Peer, Key K', Number Ta|}|}) #
evs)
==> K = K' ∨ K ∈ authKeys evs
lemma authKeysI:
Says Kas A
(Crypt (shrK A)
{|Key K, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key K, Number Ta|}|})
∈ set evs
==> K ∈ authKeys evs
lemma authKeys_used:
K ∈ authKeys evs ==> Key K ∈ used evs
lemma Says_ticket_parts:
Says S A (Crypt K {|SesKey, B, TimeStamp, Ticket|}) ∈ set evs
==> Ticket ∈ parts (knows Spy evs)
lemma Gets_ticket_parts:
[| Gets A (Crypt K {|SesKey, Peer, Ta, Ticket|}) ∈ set evs; evs ∈ kerbIV_gets |]
==> Ticket ∈ parts (knows Spy evs)
lemma Oops_range_spies1:
[| Says Kas A (Crypt KeyA {|Key authK, Peer, Ta, authTicket|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> authK ∉ range shrK ∧ authK ∈ symKeys
lemma Oops_range_spies2:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Ts, servTicket|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> servK ∉ range shrK ∧ servK ∈ symKeys
lemma Spy_see_shrK:
evs ∈ kerbIV_gets ==> (Key (shrK A) ∈ parts (knows Spy evs)) = (A ∈ bad)
lemma Spy_analz_shrK:
evs ∈ kerbIV_gets ==> (Key (shrK A) ∈ analz (knows Spy evs)) = (A ∈ bad)
lemma Spy_see_shrK_D:
[| Key (shrK A) ∈ parts (knows Spy evs); evs ∈ kerbIV_gets |] ==> A ∈ bad
lemma Spy_analz_shrK_D:
[| Key (shrK A) ∈ analz (knows Spy evs); evs ∈ kerbIV_gets |] ==> A ∈ bad
lemma new_keys_not_used:
[| Key K ∉ used evs; K ∈ symKeys; evs ∈ kerbIV_gets |]
==> K ∉ keysFor (parts (knows Spy evs))
lemma new_keys_not_analzd:
[| evs ∈ kerbIV_gets; K ∈ symKeys; Key K ∉ used evs |]
==> K ∉ keysFor (analz (knows Spy evs))
lemma Says_Kas_message_form:
[| Says Kas A (Crypt K {|Key authK, Agent Peer, Number Ta, authTicket|})
∈ set evs;
evs ∈ kerbIV_gets |]
==> K = shrK A ∧
Peer = Tgs ∧
authK ∉ range shrK ∧
authK ∈ authKeys evs ∧
authK ∈ symKeys ∧
authTicket = Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}
lemma SesKey_is_session_key:
[| Crypt (shrK Tgs_B) {|Agent A, Agent Tgs_B, Key SesKey, Number T|}
∈ parts (knows Spy evs);
Tgs_B ∉ bad; evs ∈ kerbIV_gets |]
==> SesKey ∉ range shrK
lemma authTicket_authentic:
[| Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}
∈ parts (knows Spy evs);
evs ∈ kerbIV_gets |]
==> Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs
lemma authTicket_crypt_authK:
[| Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}
∈ parts (knows Spy evs);
evs ∈ kerbIV_gets |]
==> authK ∈ authKeys evs
lemma Says_Tgs_message_form:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
evs ∈ kerbIV_gets |]
==> B ≠ Tgs ∧
authK ∉ range shrK ∧
authK ∈ authKeys evs ∧
authK ∈ symKeys ∧
servK ∉ range shrK ∧
servK ∉ authKeys evs ∧
servK ∈ symKeys ∧
servTicket = Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
lemma authTicket_form:
[| Crypt (shrK A) {|Key authK, Agent Tgs, Ta, authTicket|}
∈ parts (knows Spy evs);
A ∉ bad; evs ∈ kerbIV_gets |]
==> authK ∉ range shrK ∧
authK ∈ symKeys ∧
authTicket = Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Ta|}
lemma servTicket_form:
[| Crypt authK {|Key servK, Agent B, Ts, servTicket|} ∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); evs ∈ kerbIV_gets |]
==> servK ∉ range shrK ∧
servK ∈ symKeys ∧
(∃A. servTicket = Crypt (shrK B) {|Agent A, Agent B, Key servK, Ts|})
lemma Says_kas_message_form:
[| Gets A (Crypt (shrK A) {|Key authK, Agent Tgs, Ta, authTicket|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> authK ∉ range shrK ∧
authK ∈ symKeys ∧
authTicket = Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Ta|} ∨
authTicket ∈ analz (knows Spy evs)
lemma Says_tgs_message_form:
[| Gets A (Crypt authK {|Key servK, Agent B, Ts, servTicket|}) ∈ set evs;
authK ∈ symKeys; evs ∈ kerbIV_gets |]
==> servK ∉ range shrK ∧
(∃A. servTicket = Crypt (shrK B) {|Agent A, Agent B, Key servK, Ts|}) ∨
servTicket ∈ analz (knows Spy evs)
lemma authK_authentic:
[| Crypt (shrK A) {|Key authK, Peer, Ta, authTicket|} ∈ parts (knows Spy evs);
A ∉ bad; evs ∈ kerbIV_gets |]
==> Says Kas A (Crypt (shrK A) {|Key authK, Peer, Ta, authTicket|}) ∈ set evs
lemma servK_authentic:
[| Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); authK ∉ range shrK; evs ∈ kerbIV_gets |]
==> ∃A. Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs
lemma servK_authentic_bis:
[| Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); B ≠ Tgs; evs ∈ kerbIV_gets |]
==> ∃A. Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs
lemma servTicket_authentic_Tgs:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃authK.
Says Tgs A
(Crypt authK
{|Key servK, Agent B, Number Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}|})
∈ set evs
lemma K4_imp_K2:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
evs ∈ kerbIV_gets |]
==> ∃Ta. Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs
lemma u_K4_imp_K2:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
evs ∈ kerbIV_gets |]
==> ∃Ta. Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs ∧
servKlife + Ts ≤ authKlife + Ta
lemma servTicket_authentic_Kas:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃authK Ta.
Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs
lemma u_servTicket_authentic_Kas:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃authK Ta.
Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs ∧
servKlife + Ts ≤ authKlife + Ta
lemma servTicket_authentic:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃Ta authK.
Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs ∧
Says Tgs A
(Crypt authK
{|Key servK, Agent B, Number Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}|})
∈ set evs
lemma u_servTicket_authentic:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
B ≠ Tgs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃Ta authK.
Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs ∧
Says Tgs A
(Crypt authK
{|Key servK, Agent B, Number Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}|})
∈ set evs ∧
servKlife + Ts ≤ authKlife + Ta
lemma u_NotexpiredSK_NotexpiredAK:
[| ¬ expiredSK Ts evs; servKlife + Ts ≤ authKlife + Ta |] ==> ¬ expiredAK Ta evs
lemma K3_imp_K2:
[| Says A Tgs {|authTicket, Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs;
A ∉ bad; evs ∈ kerbIV_gets |]
==> ∃Ta. Says Kas A
(Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs
lemma Key_unique_SesKey:
[| Crypt K {|Key SesKey, Agent B, T, Ticket|} ∈ parts (knows Spy evs);
Crypt K' {|Key SesKey, Agent B', T', Ticket'|} ∈ parts (knows Spy evs);
Key SesKey ∉ analz (knows Spy evs); evs ∈ kerbIV_gets |]
==> K = K' ∧ B = B' ∧ T = T' ∧ Ticket = Ticket'
lemma Tgs_authenticates_A:
[| Crypt authK {|Agent A, Number T2.0|} ∈ parts (knows Spy evs);
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}
∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); A ∉ bad; evs ∈ kerbIV_gets |]
==> ∃B. Says A Tgs
{|Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|},
Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs
lemma Says_K5:
[| Crypt servK {|Agent A, Number T3.0|} ∈ parts (knows Spy evs);
Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
Key servK ∉ analz (knows Spy evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |]
==> Says A B {|servTicket, Crypt servK {|Agent A, Number T3.0|}|} ∈ set evs
lemma unique_CryptKey:
[| Crypt (shrK B) {|Agent A, Agent B, Key SesKey, T|} ∈ parts (knows Spy evs);
Crypt (shrK B') {|Agent A', Agent B', Key SesKey, T'|}
∈ parts (knows Spy evs);
Key SesKey ∉ analz (knows Spy evs); evs ∈ kerbIV_gets |]
==> A = A' ∧ B = B' ∧ T = T'
lemma Says_K6:
[| Crypt servK (Number T3.0) ∈ parts (knows Spy evs);
Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
Key servK ∉ analz (knows Spy evs); A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |]
==> Says B A (Crypt servK (Number T3.0)) ∈ set evs
lemma servK_authentic_ter:
[| Says Kas A (Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs;
Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); evs ∈ kerbIV_gets |]
==> Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs
lemma unique_authKeys:
[| Says Kas A (Crypt Ka {|Key authK, Agent Tgs, Ta, X|}) ∈ set evs;
Says Kas A' (Crypt Ka' {|Key authK, Agent Tgs, Ta', X'|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> A = A' ∧ Ka = Ka' ∧ Ta = Ta' ∧ X = X'
lemma unique_servKeys:
[| Says Tgs A (Crypt K {|Key servK, Agent B, Ts, X|}) ∈ set evs;
Says Tgs A' (Crypt K' {|Key servK, Agent B', Ts', X'|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> A = A' ∧ B = B' ∧ K = K' ∧ Ts = Ts' ∧ X = X'
lemma Kas_Unique:
[| Says Kas A (Crypt Ka {|Key authK, Agent Tgs, Ta, authTicket|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> Unique Says Kas A (Crypt Ka {|Key authK, Agent Tgs, Ta, authTicket|}) on evs
lemma Tgs_Unique:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Ts, servTicket|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> Unique Says Tgs A
(Crypt authK {|Key servK, Agent B, Ts, servTicket|}) on evs
lemma not_AKcryptSK_Nil:
¬ AKcryptSK authK servK []
lemma AKcryptSKI:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, X|}) ∈ set evs;
evs ∈ kerbIV_gets |]
==> AKcryptSK authK servK evs
lemma AKcryptSK_Says:
AKcryptSK authK servK (Says S A X # evs) =
(Tgs = S ∧
(∃B Ts. X = Crypt authK
{|Key servK, Agent B, Number Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}|}) ∨
AKcryptSK authK servK evs)
lemma Auth_fresh_not_AKcryptSK:
[| Key authK ∉ used evs; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK authK servK evs
lemma Serv_fresh_not_AKcryptSK:
Key servK ∉ used evs ==> ¬ AKcryptSK authK servK evs
lemma authK_not_AKcryptSK:
[| Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, tk|}
∈ parts (knows Spy evs);
evs ∈ kerbIV_gets |]
==> ¬ AKcryptSK K authK evs
lemma servK_not_AKcryptSK:
[| Crypt (shrK B) {|Agent A, Agent B, Key SK, Number Ts|}
∈ parts (knows Spy evs);
Key SK ∉ analz (knows Spy evs); SK ∈ symKeys; B ≠ Tgs; evs ∈ kerbIV_gets |]
==> ¬ AKcryptSK SK K evs
lemma shrK_not_AKcryptSK:
evs ∈ kerbIV_gets ==> ¬ AKcryptSK K (shrK A) evs
lemma Says_Tgs_AKcryptSK:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, X|}) ∈ set evs;
authK' ≠ authK; evs ∈ kerbIV_gets |]
==> ¬ AKcryptSK authK' servK evs
lemma not_different_AKcryptSK:
[| AKcryptSK authK servK evs; authK' ≠ authK; evs ∈ kerbIV_gets |]
==> ¬ AKcryptSK authK' servK evs ∧ servK ∈ symKeys
lemma AKcryptSK_not_AKcryptSK:
[| AKcryptSK authK servK evs; evs ∈ kerbIV_gets |] ==> ¬ AKcryptSK servK K evs
lemma Key_analz_image_Key_lemma:
P --> Key K ∈ analz (Key ` KK ∪ H) --> K ∈ KK ∨ Key K ∈ analz H
==> P --> (Key K ∈ analz (Key ` KK ∪ H)) = (K ∈ KK ∨ Key K ∈ analz H)
lemma AKcryptSK_analz_insert:
[| AKcryptSK K K' evs; K ∈ symKeys; evs ∈ kerbIV_gets |]
==> Key K' ∈ analz (insert (Key K) (knows Spy evs))
lemma authKeys_are_not_AKcryptSK:
[| K ∈ authKeys evs ∪ range shrK; evs ∈ kerbIV_gets |]
==> ∀SK. ¬ AKcryptSK SK K evs ∧ K ∈ symKeys
lemma not_authKeys_not_AKcryptSK:
[| K ∉ authKeys evs; K ∉ range shrK; evs ∈ kerbIV_gets |]
==> ∀SK. ¬ AKcryptSK K SK evs
lemma Oops2_not_AKcryptSK:
[| evs ∈ kerbIV_gets;
Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs |]
==> ¬ AKcryptSK servK SK evs
lemma Key_analz_image_Key:
[| evs ∈ kerbIV_gets; SK ∈ symKeys ∧ KK ⊆ - range shrK;
∀K∈KK. ¬ AKcryptSK K SK evs |]
==> (Key SK ∈ analz (Key ` KK ∪ knows Spy evs)) =
(SK ∈ KK ∨ Key SK ∈ analz (knows Spy evs))
lemma analz_insert_freshK1:
[| evs ∈ kerbIV_gets; K ∈ authKeys evs ∪ range shrK; SesKey ∉ range shrK |]
==> (Key K ∈ analz (insert (Key SesKey) (knows Spy evs))) =
(K = SesKey ∨ Key K ∈ analz (knows Spy evs))
lemma analz_insert_freshK2:
[| evs ∈ kerbIV_gets; servK ∉ authKeys evs; servK ∉ range shrK; K ∈ symKeys |]
==> (Key K ∈ analz (insert (Key servK) (knows Spy evs))) =
(K = servK ∨ Key K ∈ analz (knows Spy evs))
lemma analz_insert_freshK3:
[| AKcryptSK authK servK evs; authK' ≠ authK; authK' ∉ range shrK;
evs ∈ kerbIV_gets |]
==> (Key servK ∈ analz (insert (Key authK') (knows Spy evs))) =
(servK = authK' ∨ Key servK ∈ analz (knows Spy evs))
lemma analz_insert_freshK3_bis:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
authK ≠ authK'; authK' ∉ range shrK; evs ∈ kerbIV_gets |]
==> (Key servK ∈ analz (insert (Key authK') (knows Spy evs))) =
(servK = authK' ∨ Key servK ∈ analz (knows Spy evs))
lemma authK_compromises_servK:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
authK ∈ symKeys; Key authK ∈ analz (knows Spy evs); evs ∈ kerbIV_gets |]
==> Key servK ∈ analz (knows Spy evs)
lemma servK_notin_authKeysD:
[| Crypt authK
{|Key servK, Agent B, Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Ts|}|}
∈ parts (knows Spy evs);
Key servK ∉ analz (knows Spy evs); B ≠ Tgs; evs ∈ kerbIV_gets |]
==> servK ∉ authKeys evs
lemma Confidentiality_Kas_lemma:
[| authK ∈ symKeys; A ∉ bad; evs ∈ kerbIV_gets;
Says Kas A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs;
Key authK ∈ analz (knows Spy evs) |]
==> expiredAK Ta evs
lemma Confidentiality_Kas:
[| Says Kas A (Crypt Ka {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs;
¬ expiredAK Ta evs; A ∉ bad; evs ∈ kerbIV_gets |]
==> Key authK ∉ analz (knows Spy evs)
lemma Confidentiality_lemma:
[| Says Tgs A
(Crypt authK
{|Key servK, Agent B, Number Ts,
Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}|})
∈ set evs;
Key authK ∉ analz (knows Spy evs); servK ∈ symKeys; A ∉ bad; B ∉ bad;
evs ∈ kerbIV_gets; Key servK ∈ analz (knows Spy evs) |]
==> expiredSK Ts evs
lemma Confidentiality_Tgs:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
Key authK ∉ analz (knows Spy evs); ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad;
evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma Confidentiality_Tgs_bis:
[| Says Kas A (Crypt Ka {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs;
Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
¬ expiredAK Ta evs; ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad;
evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma Confidentiality_Tgs_ter:
[| Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}
∈ parts (knows Spy evs);
evs ∈ kerbIV_gets;
Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
¬ expiredAK Ta evs; ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad;
evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma Confidentiality_Auth_A:
[| Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|}
∈ parts (knows Spy evs);
A ∉ bad; evs ∈ kerbIV_gets; ¬ expiredAK Ta evs; A ∉ bad; evs ∈ kerbIV_gets |]
==> Key authK ∉ analz (knows Spy evs)
lemma servK_authentic_bis_r:
[| Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|}
∈ parts (knows Spy evs);
Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
¬ expiredAK Ta evs; A ∉ bad; evs ∈ kerbIV_gets |]
==> Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs
lemma Confidentiality_Serv_A:
[| Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|}
∈ parts (knows Spy evs);
Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
¬ expiredAK Ta evs; ¬ expiredSK Ts evs; A ∉ bad; B ∉ bad;
evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma Confidentiality_B:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|}
∈ parts (knows Spy evs);
¬ expiredSK Ts evs; ¬ expiredAK Ta evs; A ∉ bad; B ∉ bad; B ≠ Tgs;
evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma u_Confidentiality_B:
[| Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}
∈ parts (knows Spy evs);
¬ expiredSK Ts evs; A ∉ bad; B ∉ bad; B ≠ Tgs; evs ∈ kerbIV_gets |]
==> Key servK ∉ analz (knows Spy evs)
lemma A_authenticates_B:
[| Crypt servK (Number T3.0) ∈ parts (knows Spy evs);
Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}
∈ parts (knows Spy evs);
Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|}
∈ parts (knows Spy evs);
Key authK ∉ analz (knows Spy evs); Key servK ∉ analz (knows Spy evs);
A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |]
==> Says B A (Crypt servK (Number T3.0)) ∈ set evs
lemma shrK_in_initState_Server:
Key (shrK A) ∈ initState Kas
lemma shrK_in_knows_Server:
Key (shrK A) ∈ knows Kas evs
lemma A_authenticates_and_keydist_to_Kas:
[| Gets A (Crypt (shrK A) {|Key authK, Peer, Ta, authTicket|}) ∈ set evs;
A ∉ bad; evs ∈ kerbIV_gets |]
==> Says Kas A (Crypt (shrK A) {|Key authK, Peer, Ta, authTicket|}) ∈ set evs ∧
Key authK ∈ analz (knows Kas evs)
lemma K3_imp_Gets:
[| Says A Tgs
{|Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|},
Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs;
A ∉ bad; evs ∈ kerbIV_gets |]
==> Gets A
(Crypt (shrK A)
{|Key authK, Agent Tgs, Number Ta,
Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}|})
∈ set evs
lemma Tgs_authenticates_and_keydist_to_A:
[| Gets Tgs
{|Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|},
Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs;
Key authK ∉ analz (knows Spy evs); A ∉ bad; evs ∈ kerbIV_gets |]
==> ∃B. Says A Tgs
{|Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|},
Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs ∧
Key authK ∈ analz (knows A evs)
lemma K4_imp_Gets:
[| Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs;
evs ∈ kerbIV_gets |]
==> ∃Ta X. Gets Tgs
{|Crypt (shrK Tgs) {|Agent A, Agent Tgs, Key authK, Number Ta|}, X|}
∈ set evs
lemma A_authenticates_and_keydist_to_Tgs:
[| Gets A (Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs;
Gets A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|}) ∈ set evs;
Key authK ∉ analz (knows Spy evs); A ∉ bad; evs ∈ kerbIV_gets |]
==> Says Tgs A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs ∧
Key authK ∈ analz (knows Tgs evs) ∧ Key servK ∈ analz (knows Tgs evs)
lemma K5_imp_Gets:
[| Says A B {|servTicket, Crypt servK {|Agent A, Number T3.0|}|} ∈ set evs;
A ∉ bad; evs ∈ kerbIV_gets |]
==> ∃authK Ts authTicket T2.
Gets A (Crypt authK {|Key servK, Agent B, Number Ts, servTicket|})
∈ set evs ∧
Says A Tgs {|authTicket, Crypt authK {|Agent A, Number T2|}, Agent B|}
∈ set evs
lemma K3_imp_Gets:
[| Says A Tgs {|authTicket, Crypt authK {|Agent A, Number T2.0|}, Agent B|}
∈ set evs;
A ∉ bad; evs ∈ kerbIV_gets |]
==> ∃Ta. Gets A (Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs
lemma B_authenticates_and_keydist_to_A:
[| Gets B
{|Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|},
Crypt servK {|Agent A, Number T3.0|}|}
∈ set evs;
Key servK ∉ analz (knows Spy evs); A ∉ bad; B ∉ bad; B ≠ Tgs;
evs ∈ kerbIV_gets |]
==> Says A B
{|Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|},
Crypt servK {|Agent A, Number T3.0|}|}
∈ set evs ∧
Key servK ∈ analz (knows A evs)
lemma K6_imp_Gets:
[| Says B A (Crypt servK (Number T3.0)) ∈ set evs; B ∉ bad; evs ∈ kerbIV_gets |]
==> ∃Ts X. Gets B
{|Crypt (shrK B) {|Agent A, Agent B, Key servK, Number Ts|}, X|}
∈ set evs
lemma A_authenticates_and_keydist_to_B:
[| Gets A
{|Crypt authK {|Key servK, Agent B, Number Ts, servTicket|},
Crypt servK (Number T3.0)|}
∈ set evs;
Gets A (Crypt (shrK A) {|Key authK, Agent Tgs, Number Ta, authTicket|})
∈ set evs;
Key authK ∉ analz (knows Spy evs); Key servK ∉ analz (knows Spy evs);
A ∉ bad; B ∉ bad; evs ∈ kerbIV_gets |]
==> Says B A (Crypt servK (Number T3.0)) ∈ set evs ∧
Key servK ∈ analz (knows B evs)