# HG changeset patch # User paulson # Date 1060688103 -7200 # Node ID 2e31b8cc8788308bf6d47cf439cb08c2784b6a62 # Parent 7195c9b0423f3ddabf4143d467cb99130b6222b4 ZhouGollmann: new example (fair non-repudiation protocol) diff -r 7195c9b0423f -r 2e31b8cc8788 src/HOL/Auth/CertifiedEmail.thy --- a/src/HOL/Auth/CertifiedEmail.thy Fri Aug 08 15:05:11 2003 +0200 +++ b/src/HOL/Auth/CertifiedEmail.thy Tue Aug 12 13:35:03 2003 +0200 @@ -39,12 +39,12 @@ Fake: --{*The Spy may say anything he can say. The sender field is correct, but agents don't use that information.*} - "[| evsf \ certified_mail; X \ synth(analz(knows Spy evsf))|] + "[| evsf \ certified_mail; X \ synth(analz(spies evsf))|] ==> Says Spy B X # evsf \ certified_mail" FakeSSL: --{*The Spy may open SSL sessions with TTP, who is the only agent equipped with the necessary credentials to serve as an SSL server.*} - "[| evsfssl \ certified_mail; X \ synth(analz(knows Spy evsfssl))|] + "[| evsfssl \ certified_mail; X \ synth(analz(spies evsfssl))|] ==> Notes TTP {|Agent Spy, Agent TTP, X|} # evsfssl \ certified_mail" CM1: --{*The sender approaches the recipient. The message is a number.*} @@ -89,6 +89,9 @@ ==> Gets B X#evsr \ certified_mail" +declare Says_imp_knows_Spy [THEN analz.Inj, dest] +declare analz_into_parts [dest] + (*A "possibility property": there are traces that reach the end*) lemma "\S2TTP. \evs \ certified_mail. Says TTP S (Crypt (priSK TTP) S2TTP) \ set evs" @@ -118,7 +121,7 @@ "[|Gets R {|Agent A, Agent B, em, Number AO, Number cleartext, Nonce q, S2TTP|} \ set evs; evs \ certified_mail|] - ==> S2TTP \ analz(knows Spy evs)" + ==> S2TTP \ analz(spies evs)" apply (drule Gets_imp_Says, simp) apply (blast dest: Says_imp_knows_Spy analz.Inj) done @@ -128,7 +131,7 @@ lemma hr_form_lemma [rule_format]: "evs \ certified_mail - ==> hr \ synth (analz (knows Spy evs)) --> + ==> hr \ synth (analz (spies evs)) --> (\S2TTP. Notes TTP {|Agent R, Agent TTP, S2TTP, pwd, hr|} \ set evs --> (\clt q S em. hr = Hash {|Number clt, Nonce q, response S R q, em|}))" @@ -142,39 +145,39 @@ lemma hr_form: "[|Notes TTP {|Agent R, Agent TTP, S2TTP, pwd, hr|} \ set evs; evs \ certified_mail|] - ==> hr \ synth (analz (knows Spy evs)) | + ==> hr \ synth (analz (spies evs)) | (\clt q S em. hr = Hash {|Number clt, Nonce q, response S R q, em|})" by (blast intro: hr_form_lemma) -lemma Spy_dont_know_private_keys [rule_format]: - "evs \ certified_mail - ==> Key (privateKey b A) \ parts (spies evs) --> A \ bad" +lemma Spy_dont_know_private_keys [dest!]: + "[|Key (privateKey b A) \ parts (spies evs); evs \ certified_mail|] + ==> A \ bad" +apply (erule rev_mp) apply (erule certified_mail.induct, simp_all) txt{*Fake*} -apply (blast dest: Fake_parts_insert[THEN subsetD] - analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_insert_in_Un); txt{*Message 1*} apply blast txt{*Message 3*} apply (frule_tac hr_form, assumption) apply (elim disjE exE) apply (simp_all add: parts_insert2) - apply (force dest!: parts_insert_subset_Un[THEN [2] rev_subsetD] - analz_subset_parts[THEN subsetD], blast) + apply (force dest!: parts_insert_subset_Un [THEN [2] rev_subsetD] + analz_subset_parts [THEN subsetD], blast) done lemma Spy_know_private_keys_iff [simp]: "evs \ certified_mail ==> (Key (privateKey b A) \ parts (spies evs)) = (A \ bad)" -by (blast intro: Spy_dont_know_private_keys parts.Inj) +by (blast intro: elim:); lemma Spy_dont_know_TTPKey_parts [simp]: - "evs \ certified_mail ==> Key (privateKey b TTP) \ parts(knows Spy evs)" + "evs \ certified_mail ==> Key (privateKey b TTP) \ parts(spies evs)" by simp lemma Spy_dont_know_TTPKey_analz [simp]: - "evs \ certified_mail ==> Key (privateKey b TTP) \ analz(knows Spy evs)" -by (force dest!: analz_subset_parts[THEN subsetD]) + "evs \ certified_mail ==> Key (privateKey b TTP) \ analz(spies evs)" +by auto text{*Thus, prove any goal that assumes that @{term Spy} knows a private key belonging to @{term TTP}*} @@ -192,10 +195,9 @@ apply (erule certified_mail.induct, simp_all) apply (blast intro:parts_insertI) txt{*Fake SSL*} -apply (blast dest: analz_subset_parts[THEN subsetD] parts.Body) +apply (blast dest: parts.Body) txt{*Message 2*} -apply (blast dest!: Says_imp_knows_Spy [THEN parts.Inj] Gets_imp_Says - elim!: knows_Spy_partsEs) +apply (blast dest!: Gets_imp_Says elim!: knows_Spy_partsEs) txt{*Message 3*} apply (frule_tac hr_form, assumption) apply (elim disjE exE) @@ -207,8 +209,7 @@ "evs \ certified_mail ==> Key (RPwd A) \ parts(spies evs) --> A \ bad" apply (erule certified_mail.induct, simp_all) txt{*Fake*} -apply (blast dest: Fake_parts_insert[THEN subsetD] - analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_insert_in_Un); txt{*Message 1*} apply blast txt{*Message 3*} @@ -216,18 +217,18 @@ apply (frule_tac hr_form, assumption) apply (elim disjE exE) apply (simp_all add: parts_insert2) -apply (force dest!: parts_insert_subset_Un[THEN [2] rev_subsetD] - analz_subset_parts[THEN subsetD]) +apply (force dest!: parts_insert_subset_Un [THEN [2] rev_subsetD] + analz_subset_parts [THEN subsetD]) done lemma Spy_know_RPwd_iff [simp]: - "evs \ certified_mail ==> (Key (RPwd A) \ parts(knows Spy evs)) = (A\bad)" + "evs \ certified_mail ==> (Key (RPwd A) \ parts(spies evs)) = (A\bad)" by (auto simp add: Spy_dont_know_RPwd) lemma Spy_analz_RPwd_iff [simp]: - "evs \ certified_mail ==> (Key (RPwd A) \ analz(knows Spy evs)) = (A\bad)" -by (auto simp add: Spy_dont_know_RPwd [OF _ analz_subset_parts[THEN subsetD]]) + "evs \ certified_mail ==> (Key (RPwd A) \ analz(spies evs)) = (A\bad)" +by (auto simp add: Spy_dont_know_RPwd [OF _ analz_subset_parts [THEN subsetD]]) text{*Unused, but a guarantee of sorts*} @@ -237,16 +238,15 @@ apply (erule rev_mp) apply (erule certified_mail.induct, simp_all) txt{*Fake*} -apply (blast dest: Spy_dont_know_private_keys Fake_parts_insert[THEN subsetD] - analz_subset_parts[THEN subsetD]) +apply (blast dest: Spy_dont_know_private_keys Fake_parts_insert_in_Un) txt{*Message 1*} apply blast txt{*Message 3*} apply (frule_tac hr_form, assumption) apply (elim disjE exE) -apply (simp_all add: parts_insert2) -apply (force dest!: parts_insert_subset_Un[THEN [2] rev_subsetD] - analz_subset_parts[THEN subsetD], blast) +apply (simp_all add: parts_insert2 parts_insert_knows_A) + apply (blast dest!: Fake_parts_sing_imp_Un) +apply (blast intro: elim:); done @@ -255,8 +255,8 @@ lemma analz_image_freshK [rule_format]: "evs \ certified_mail ==> \K KK. invKey (pubEK TTP) \ KK --> - (Key K \ analz (Key`KK Un (knows Spy evs))) = - (K \ KK | Key K \ analz (knows Spy evs))" + (Key K \ analz (Key`KK Un (spies evs))) = + (K \ KK | Key K \ analz (spies evs))" apply (erule certified_mail.induct) apply (drule_tac [6] A=TTP in symKey_neq_priEK) apply (erule_tac [6] disjE [OF hr_form]) @@ -272,8 +272,8 @@ lemma analz_insert_freshK: "[| evs \ certified_mail; KAB \ invKey (pubEK TTP) |] ==> - (Key K \ analz (insert (Key KAB) (knows Spy evs))) = - (K = KAB | Key K \ analz (knows Spy evs))" + (Key K \ analz (insert (Key KAB) (spies evs))) = + (K = KAB | Key K \ analz (spies evs))" by (simp only: analz_image_freshK analz_image_freshK_simps) text{*@{term S2TTP} must have originated from a valid sender @@ -284,11 +284,11 @@ by (blast dest!: Notes_imp_used) -(*The weaker version, replacing "used evs" by "parts (knows Spy evs)", +(*The weaker version, replacing "used evs" by "parts (spies evs)", isn't inductive: message 3 case can't be proved *) lemma S2TTP_sender_lemma [rule_format]: "evs \ certified_mail ==> - Key K \ analz (knows Spy evs) --> + Key K \ analz (spies evs) --> (\AO. Crypt (pubEK TTP) {|Agent S, Number AO, Key K, Agent R, hs|} \ used evs --> (\m ctxt q. @@ -302,11 +302,11 @@ apply (drule_tac [5] CM2_S2TTP_parts_knows_Spy, simp) apply (simp add: used_Nil Crypt_notin_initState, simp_all) txt{*Fake*} -apply (blast dest: Fake_parts_sing[THEN subsetD] - dest!: analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_sing [THEN subsetD] + dest!: analz_subset_parts [THEN subsetD]) txt{*Fake SSL*} -apply (blast dest: Fake_parts_sing[THEN subsetD] - dest: analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_sing [THEN subsetD] + dest: analz_subset_parts [THEN subsetD]) txt{*Message 1*} apply (clarsimp, blast) txt{*Message 2*} @@ -319,7 +319,7 @@ lemma S2TTP_sender: "[|Crypt (pubEK TTP) {|Agent S, Number AO, Key K, Agent R, hs|} \ used evs; - Key K \ analz (knows Spy evs); + Key K \ analz (spies evs); evs \ certified_mail|] ==> \m ctxt q. hs = Hash{|Number ctxt, Nonce q, response S R q, Crypt K (Number m)|} & @@ -353,7 +353,7 @@ where @{term K} is secure.*} lemma Key_unique_lemma [rule_format]: "evs \ certified_mail ==> - Key K \ analz (knows Spy evs) --> + Key K \ analz (spies evs) --> (\m cleartext q hs. Says S R {|Agent S, Agent TTP, Crypt K (Number m), Number AO, @@ -367,10 +367,11 @@ Crypt (pubEK TTP) {|Agent S', Number AO', Key K, Agent R', hs'|}|} \ set evs --> R' = R & S' = S & AO' = AO & hs' = hs))" apply (erule certified_mail.induct, analz_mono_contra, simp_all) -txt{*Fake*} -apply (blast dest!: usedI S2TTP_sender analz_subset_parts[THEN subsetD]) -txt{*Message 1*} -apply (blast dest!: Says_imp_knows_Spy [THEN parts.Inj] new_keys_not_used Crypt_imp_keysFor) + prefer 2 + txt{*Message 1*} + apply (blast dest!: Says_imp_knows_Spy [THEN parts.Inj] new_keys_not_used Crypt_imp_keysFor) +txt{*Fake*} +apply (auto dest!: usedI S2TTP_sender analz_subset_parts [THEN subsetD]) done text{*The key determines the sender, recipient and protocol options.*} @@ -385,7 +386,7 @@ Number cleartext', Nonce q', Crypt (pubEK TTP) {|Agent S', Number AO', Key K, Agent R', hs'|}|} \ set evs; - Key K \ analz (knows Spy evs); + Key K \ analz (spies evs); evs \ certified_mail|] ==> R' = R & S' = S & AO' = AO & hs' = hs" by (rule Key_unique_lemma, assumption+) @@ -400,7 +401,7 @@ "[|Says S R {|Agent S, Agent TTP, Crypt K (Number m), Number AO, Number cleartext, Nonce q, S2TTP|} \ set evs; S2TTP = Crypt (pubEK TTP) {|Agent S, Number AO, Key K, Agent R, hs|}; - Key K \ analz(knows Spy evs); + Key K \ analz(spies evs); evs \ certified_mail; S\Spy|] ==> R \ bad & Gets S (Crypt (priSK TTP) S2TTP) \ set evs" @@ -430,7 +431,7 @@ S2TTP = Crypt (pubEK TTP) {|Agent S, Number AO, Key K, Agent R, hs|}; evs \ certified_mail; S\Spy; R \ bad|] - ==> Key K \ analz(knows Spy evs)" + ==> Key K \ analz(spies evs)" by (blast dest: Spy_see_encrypted_key_imp) @@ -471,19 +472,19 @@ apply (erule ssubst) apply (erule certified_mail.induct, simp_all) txt{*Fake*} -apply (blast dest: Fake_parts_sing[THEN subsetD] - dest!: analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_sing [THEN subsetD] + dest!: analz_subset_parts [THEN subsetD]) txt{*Fake SSL*} -apply (blast dest: Fake_parts_sing[THEN subsetD] - dest!: analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_sing [THEN subsetD] + dest!: analz_subset_parts [THEN subsetD]) txt{*Message 2*} apply (drule CM2_S2TTP_parts_knows_Spy, assumption) apply (force dest: parts_cut) txt{*Message 3*} apply (frule_tac hr_form, assumption) apply (elim disjE exE, simp_all) -apply (blast dest: Fake_parts_sing[THEN subsetD] - dest!: analz_subset_parts[THEN subsetD]) +apply (blast dest: Fake_parts_sing [THEN subsetD] + dest!: analz_subset_parts [THEN subsetD]) done end diff -r 7195c9b0423f -r 2e31b8cc8788 src/HOL/Auth/Message.thy --- a/src/HOL/Auth/Message.thy Fri Aug 08 15:05:11 2003 +0200 +++ b/src/HOL/Auth/Message.thy Tue Aug 12 13:35:03 2003 +0200 @@ -683,10 +683,10 @@ done lemma analz_conj_parts [simp]: "(X \ analz H & X \ parts H) = (X \ analz H)" -by (blast intro: analz_subset_parts [THEN [2] rev_subsetD]) +by (blast intro: analz_subset_parts [THEN subsetD]) lemma analz_disj_parts [simp]: "(X \ analz H | X \ parts H) = (X \ parts H)" -by (blast intro: analz_subset_parts [THEN [2] rev_subsetD]) +by (blast intro: analz_subset_parts [THEN subsetD]) (*Without this equation, other rules for synth and analz would yield redundant cases*) @@ -994,6 +994,8 @@ apply (simp add: parts_mono) done +lemmas Fake_parts_sing_imp_Un = Fake_parts_sing [THEN [2] rev_subsetD] + method_setup spy_analz = {* Method.ctxt_args (fn ctxt => Method.METHOD (fn facts => diff -r 7195c9b0423f -r 2e31b8cc8788 src/HOL/Auth/ROOT.ML --- a/src/HOL/Auth/ROOT.ML Fri Aug 08 15:05:11 2003 +0200 +++ b/src/HOL/Auth/ROOT.ML Tue Aug 12 13:35:03 2003 +0200 @@ -21,6 +21,8 @@ time_use_thy "Yahalom"; time_use_thy "Yahalom2"; time_use_thy "Yahalom_Bad"; +time_use_thy "ZhouGollmann"; + (*Public-key protocols*) time_use_thy "NS_Public_Bad"; diff -r 7195c9b0423f -r 2e31b8cc8788 src/HOL/Auth/ZhouGollmann.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Auth/ZhouGollmann.thy Tue Aug 12 13:35:03 2003 +0200 @@ -0,0 +1,463 @@ +(* Title: HOL/Auth/ZhouGollmann + ID: $Id$ + Author: Giampaolo Bella and L C Paulson, Cambridge Univ Computer Lab + Copyright 2003 University of Cambridge + +The protocol of + Jianying Zhou and Dieter Gollmann, + A Fair Non-Repudiation Protocol, + Security and Privacy 1996 (Oakland) + 55-61 +*) + +theory ZhouGollmann = Public: + +syntax + TTP :: agent + +translations + "TTP" == "Server" + +syntax + f_sub :: nat + f_nro :: nat + f_nrr :: nat + f_con :: nat + +translations + "f_sub" == "5" + "f_nro" == "2" + "f_nrr" == "3" + "f_con" == "4" + + +constdefs + broken :: "agent set" + --{*the compromised honest agents; TTP is included as it's not allowed to + use the protocol*} + "broken == insert TTP (bad - {Spy})" + +declare broken_def [simp] + +consts zg :: "event list set" + +inductive zg + intros + + Nil: "[] \ zg" + + Fake: "[| evsf \ zg; X \ synth (analz (spies evsf)) |] + ==> Says Spy B X # evsf \ zg" + +Reception: "[| evsr \ zg; A \ B; Says A B X \ set evsr |] + ==> Gets B X # evsr \ zg" + + (*L is fresh for honest agents. + We don't require K to be fresh because we don't bother to prove secrecy! + We just assume that the protocol's objective is to deliver K fairly, + rather than to keep M secret.*) + ZG1: "[| evs1 \ zg; Nonce L \ used evs1; C = Crypt K (Number m); + K \ symKeys; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}|] + ==> Says A B {|Number f_nro, Agent B, Nonce L, C, NRO|} # evs1 \ zg" + + (*B must check that NRO is A's signature to learn the sender's name*) + ZG2: "[| evs2 \ zg; + Gets B {|Number f_nro, Agent B, Nonce L, C, NRO|} \ set evs2; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}|] + ==> Says B A {|Number f_nrr, Agent A, Nonce L, NRR|} # evs2 \ zg" + + (*K is symmetric must be repeated IF there's spy*) + (*A must check that NRR is B's signature to learn the sender's name*) + (*without spy, the matching label would be enough*) + ZG3: "[| evs3 \ zg; C = Crypt K M; K \ symKeys; + Says A B {|Number f_nro, Agent B, Nonce L, C, NRO|} \ set evs3; + Gets A {|Number f_nrr, Agent A, Nonce L, NRR|} \ set evs3; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}|] + ==> Says A TTP {|Number f_sub, Agent B, Nonce L, Key K, sub_K|} + # evs3 \ zg" + + (*TTP checks that sub_K is A's signature to learn who issued K, then + gives credentials to A and B. The Notes event models the availability of + the credentials, but the act of fetching them is not modelled.*) + (*Also said TTP_prepare_ftp*) + ZG4: "[| evs4 \ zg; K \ symKeys; + Gets TTP {|Number f_sub, Agent B, Nonce L, Key K, sub_K|} + \ set evs4; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + con_K = Crypt (priK TTP) {|Number f_con, Agent A, Agent B, + Nonce L, Key K|}|] + ==> Notes TTP {|Number f_con, Agent A, Agent B, Nonce L, Key K, con_K|} + # evs4 \ zg" + + +declare Says_imp_knows_Spy [THEN analz.Inj, dest] +declare Fake_parts_insert_in_Un [dest] +declare analz_into_parts [dest] + +declare symKey_neq_priEK [simp] +declare symKey_neq_priEK [THEN not_sym, simp] + + +subsection {*Basic Lemmas*} + +lemma Gets_imp_Says: + "[| Gets B X \ set evs; evs \ zg |] ==> \A. Says A B X \ set evs" +apply (erule rev_mp) +apply (erule zg.induct, auto) +done + +lemma Gets_imp_knows_Spy: + "[| Gets B X \ set evs; evs \ zg |] ==> X \ spies evs" +by (blast dest!: Gets_imp_Says Says_imp_knows_Spy) + + +text{*Lets us replace proofs about @{term "used evs"} by simpler proofs +about @{term "parts (spies evs)"}.*} +lemma Crypt_used_imp_spies: + "[| Crypt K X \ used evs; K \ priK TTP; evs \ zg |] + ==> Crypt K X \ parts (spies evs)" +apply (erule rev_mp) +apply (erule zg.induct) +apply (simp_all add: parts_insert_knows_A) +done + +lemma Notes_TTP_imp_Gets: + "[|Notes TTP {|Number f_con, Agent A, Agent B, Nonce L, Key K, con_K |} + \ set evs; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + evs \ zg|] + ==> Gets TTP {|Number f_sub, Agent B, Nonce L, Key K, sub_K|} \ set evs" +apply (erule rev_mp) +apply (erule zg.induct, auto) +done + +text{*For reasoning about C, which is encrypted in message ZG2*} +lemma ZG2_msg_in_parts_spies: + "[|Gets B {|F, B', L, C, X|} \ set evs; evs \ zg|] + ==> C \ parts (spies evs)" +by (blast dest: Gets_imp_Says) + +(*classical regularity lemma on priK*) +lemma Spy_see_priK [simp]: + "evs \ zg ==> (Key (priK A) \ parts (spies evs)) = (A \ bad)" +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, auto) +done + +text{*So that blast can use it too*} +declare Spy_see_priK [THEN [2] rev_iffD1, dest!] + +lemma Spy_analz_priK [simp]: + "evs \ zg ==> (Key (priK A) \ analz (spies evs)) = (A \ bad)" +by auto + + +subsection{*About NRO*} + +text{*Below we prove that if @{term NRO} exists then @{term A} definitely +sent it, provided @{term A} is not broken. *} + +text{*Strong conclusion for a good agent*} +lemma NRO_authenticity_good: + "[| NRO \ parts (spies evs); + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}; + A \ bad; evs \ zg |] + ==> Says A B {|Number f_nro, Agent B, Nonce L, C, NRO|} \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, auto) +done + +text{*A compromised agent: we can't be sure whether A or the Spy sends the +message or of the precise form of the message*} +lemma NRO_authenticity_bad: + "[| NRO \ parts (spies evs); + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}; + A \ bad; evs \ zg |] + ==> \A' \ {A,Spy}. \C Y. Says A' C Y \ set evs & NRO \ parts {Y}" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) +txt{*ZG3*} + prefer 4 apply blast +txt{*ZG2*} + prefer 3 apply blast +txt{*Fake*} +apply (simp add: parts_insert_knows_A, blast) +txt{*ZG1*} +apply (auto intro!: exI) +done + +theorem NRO_authenticity: + "[| NRO \ used evs; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}; + A \ broken; evs \ zg |] + ==> \C Y. Says A C Y \ set evs & NRO \ parts {Y}" +apply auto + apply (force dest!: Crypt_used_imp_spies NRO_authenticity_good) +apply (force dest!: Crypt_used_imp_spies NRO_authenticity_bad) +done + + +subsection{*About NRR*} + +text{*Below we prove that if @{term NRR} exists then @{term B} definitely +sent it, provided @{term B} is not broken.*} + +text{*Strong conclusion for a good agent*} +lemma NRR_authenticity_good: + "[| NRR \ parts (spies evs); + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}; + B \ bad; evs \ zg |] + ==> Says B A {|Number f_nrr, Agent A, Nonce L, NRR|} \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, auto) +done + +lemma NRR_authenticity_bad: + "[| NRR \ parts (spies evs); + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}; + B \ bad; evs \ zg |] + ==> \B' \ {B,Spy}. \C Y. Says B' C Y \ set evs & NRR \ parts {Y}" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies) +apply (simp_all del: bex_simps) +txt{*ZG3*} + prefer 4 apply blast +txt{*Fake*} +apply (simp add: parts_insert_knows_A, blast) +txt{*ZG1*} +apply (auto simp del: bex_simps) +txt{*ZG2*} +apply (force intro!: exI) +done + +theorem NRR_authenticity: + "[| NRR \ used evs; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}; + B \ broken; evs \ zg |] + ==> \C Y. Says B C Y \ set evs & NRR \ parts {Y}" +apply auto + apply (force dest!: Crypt_used_imp_spies NRR_authenticity_good) +apply (force dest!: Crypt_used_imp_spies NRR_authenticity_bad) +done + + +subsection{*Proofs About @{term sub_K}*} + +text{*Below we prove that if @{term sub_K} exists then @{term A} definitely +sent it, provided @{term A} is not broken. *} + +text{*Strong conclusion for a good agent*} +lemma sub_K_authenticity_good: + "[| sub_K \ parts (spies evs); + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + A \ bad; evs \ zg |] + ==> Says A TTP {|Number f_sub, Agent B, Nonce L, Key K, sub_K|} \ set evs" +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) +txt{*Fake*} +apply (blast dest!: Fake_parts_sing_imp_Un) +done + +text{*A compromised agent: we can't be sure whether A or the Spy sends the +message or of the precise form of the message*} +lemma sub_K_authenticity_bad: + "[| sub_K \ parts (spies evs); + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + A \ bad; evs \ zg |] + ==> \A' \ {A,Spy}. \C Y. Says A' C Y \ set evs & sub_K \ parts {Y}" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies) +apply (simp_all del: bex_simps) +txt{*Fake*} +apply (simp add: parts_insert_knows_A, blast) +txt{*ZG1*} +apply (auto simp del: bex_simps) +txt{*ZG3*} +apply (force intro!: exI) +done + +theorem sub_K_authenticity: + "[| sub_K \ used evs; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + A \ broken; evs \ zg |] + ==> \C Y. Says A C Y \ set evs & sub_K \ parts {Y}" +apply auto + apply (force dest!: Crypt_used_imp_spies sub_K_authenticity_good) +apply (force dest!: Crypt_used_imp_spies sub_K_authenticity_bad) +done + + +subsection{*Proofs About @{term con_K}*} + +text{*Below we prove that if @{term con_K} exists, then @{term TTP} has it, +and therefore @{term A} and @{term B}) can get it too. Moreover, we know +that @{term A} sent @{term sub_K}*} + +lemma con_K_authenticity: + "[|con_K \ used evs; + con_K = Crypt (priK TTP) + {|Number f_con, Agent A, Agent B, Nonce L, Key K|}; + evs \ zg |] + ==> Notes TTP {|Number f_con, Agent A, Agent B, Nonce L, Key K, con_K|} + \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) +txt{*Fake*} +apply (blast dest!: Fake_parts_sing_imp_Un) +txt{*ZG2*} +apply (blast dest: parts_cut) +done + +text{*If @{term TTP} holds @{term con_K} then @{term A} sent + @{term sub_K}. We assume that @{term A} is not broken. Nothing needs to + be assumed about the form of @{term con_K}!*} +lemma Notes_TTP_imp_Says_A: + "[|Notes TTP {|Number f_con, Agent A, Agent B, Nonce L, Key K, con_K|} + \ set evs; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + A \ broken; evs \ zg|] + ==> \C Y. Says A C Y \ set evs & sub_K \ parts {Y}" +by (blast dest!: Notes_TTP_imp_Gets [THEN Gets_imp_knows_Spy, THEN parts.Inj] intro: sub_K_authenticity) + +text{*If @{term con_K} exists, then @{term A} sent @{term sub_K}.*} +theorem B_sub_K_authenticity: + "[|con_K \ used evs; + con_K = Crypt (priK TTP) {|Number f_con, Agent A, Agent B, + Nonce L, Key K|}; + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + A \ broken; B \ TTP; evs \ zg|] + ==> \C Y. Says A C Y \ set evs & sub_K \ parts {Y}" +by (blast dest: con_K_authenticity Notes_TTP_imp_Says_A) + + +subsection{*Proving fairness*} + +text{*Cannot prove that, if @{term B} has NRO, then @{term A} has her NRR. +It would appear that @{term B} has a small advantage, though it is +useless to win disputes: @{term B} needs to present @{term con_K} as well.*} + +text{*Strange: unicity of the label protects @{term A}?*} +lemma A_unicity: + "[|NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, Crypt K M|}; + NRO \ parts (spies evs); + Says A B {|Number f_nro, Agent B, Nonce L, Crypt K M', NRO'|} + \ set evs; + A \ bad; evs \ zg |] + ==> M'=M" +apply clarify +apply (erule rev_mp) +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, auto) +txt{*ZG1: freshness*} +apply (blast dest: parts.Body) +done + + +text{*Fairness lemma: if @{term sub_K} exists, then @{term A} holds +NRR. Relies on unicity of labels.*} +lemma sub_K_implies_NRR: + "[| sub_K \ parts (spies evs); + NRO \ parts (spies evs); + sub_K = Crypt (priK A) {|Number f_sub, Agent B, Nonce L, Key K|}; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, Crypt K M|}; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, Crypt K M|}; + A \ bad; evs \ zg |] + ==> Gets A {|Number f_nrr, Agent A, Nonce L, NRR|} \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) +txt{*Fake*} +apply blast +txt{*ZG1: freshness*} +apply (blast dest: parts.Body) +txt{*ZG3*} +apply (blast dest: A_unicity [OF refl]) +done + + +lemma Crypt_used_imp_L_used: + "[| Crypt (priK TTP) {|F, A, B, L, K|} \ used evs; evs \ zg |] + ==> L \ used evs" +apply (erule rev_mp) +apply (erule zg.induct, auto) +txt{*Fake*} +apply (blast dest!: Fake_parts_sing_imp_Un) +txt{*ZG2: freshness*} +apply (blast dest: parts.Body) +done + + +text{*Fairness for @{term A}: if @{term con_K} and @{term NRO} exist, +then @{term A} holds NRR. @{term A} must be uncompromised, but there is no +assumption about @{term B}.*} +theorem A_fairness_NRO: + "[|con_K \ used evs; + NRO \ parts (spies evs); + con_K = Crypt (priK TTP) + {|Number f_con, Agent A, Agent B, Nonce L, Key K|}; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, Crypt K M|}; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, Crypt K M|}; + A \ bad; evs \ zg |] + ==> Gets A {|Number f_nrr, Agent A, Nonce L, NRR|} \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) + txt{*Fake*} + apply (simp add: parts_insert_knows_A) + apply (blast dest: Fake_parts_sing_imp_Un) + txt{*ZG1*} + apply (blast dest: Crypt_used_imp_L_used) + txt{*ZG2*} + apply (blast dest: parts_cut) +txt{*ZG4*} +apply (blast intro: sub_K_implies_NRR [OF _ _ refl] + dest: Gets_imp_knows_Spy [THEN parts.Inj]) +done + +text{*Fairness for @{term B}: NRR exists at all, then @{term B} holds NRO. +@{term B} must be uncompromised, but there is no assumption about @{term +A}. *} +theorem B_fairness_NRR: + "[|NRR \ used evs; + NRR = Crypt (priK B) {|Number f_nrr, Agent A, Nonce L, C|}; + NRO = Crypt (priK A) {|Number f_nro, Agent B, Nonce L, C|}; + B \ bad; evs \ zg |] + ==> Gets B {|Number f_nro, Agent B, Nonce L, C, NRO|} \ set evs" +apply clarify +apply (erule rev_mp) +apply (erule zg.induct) +apply (frule_tac [5] ZG2_msg_in_parts_spies, simp_all) +txt{*Fake*} +apply (blast dest!: Fake_parts_sing_imp_Un) +txt{*ZG2*} +apply (blast dest: parts_cut) +done + + +text{*If @{term con_K} exists at all, then @{term B} can get it, by @{text +con_K_authenticity}. Cannot conclude that also NRO is available to @{term B}, +because if @{term A} were unfair, @{term A} could build message 3 without +building message 1, which contains NRO. *} + +end diff -r 7195c9b0423f -r 2e31b8cc8788 src/HOL/IsaMakefile --- a/src/HOL/IsaMakefile Fri Aug 08 15:05:11 2003 +0200 +++ b/src/HOL/IsaMakefile Tue Aug 12 13:35:03 2003 +0200 @@ -361,9 +361,9 @@ Auth/OtwayRees_Bad.thy Auth/Public.thy Auth/ROOT.ML \ Auth/Recur.thy Auth/Shared.thy \ Auth/TLS.thy Auth/WooLam.thy \ - Auth/Kerberos_BAN.thy \ - Auth/KerberosIV.ML Auth/KerberosIV.thy \ + Auth/Kerberos_BAN.thy Auth/KerberosIV.ML Auth/KerberosIV.thy \ Auth/Yahalom.thy Auth/Yahalom2.thy Auth/Yahalom_Bad.thy \ + Auth/ZhouGollmann.thy \ Auth/Guard/Analz.thy Auth/Guard/Extensions.thy Auth/Guard/GuardK.thy \ Auth/Guard/Guard_Public.thy Auth/Guard/Guard_Shared.thy \ Auth/Guard/Guard.thy Auth/Guard/List_Msg.thy \