15 (*Two session keys are distributed to each agent except for the initiator, |
15 (*Two session keys are distributed to each agent except for the initiator, |
16 who receives one. |
16 who receives one. |
17 Perhaps the two session keys could be bundled into a single message. |
17 Perhaps the two session keys could be bundled into a single message. |
18 *) |
18 *) |
19 inductive_set (*Server's response to the nested message*) |
19 inductive_set (*Server's response to the nested message*) |
20 respond :: "event list => (msg*msg*key)set" |
20 respond :: "event list \<Rightarrow> (msg*msg*key)set" |
21 for evs :: "event list" |
21 for evs :: "event list" |
22 where |
22 where |
23 One: "Key KAB \<notin> used evs |
23 One: "Key KAB \<notin> used evs |
24 ==> (Hash[Key(shrK A)] \<lbrace>Agent A, Agent B, Nonce NA, END\<rbrace>, |
24 ==> (Hash[Key(shrK A)] \<lbrace>Agent A, Agent B, Nonce NA, END\<rbrace>, |
25 \<lbrace>Crypt (shrK A) \<lbrace>Key KAB, Agent B, Nonce NA\<rbrace>, END\<rbrace>, |
25 \<lbrace>Crypt (shrK A) \<lbrace>Key KAB, Agent B, Nonce NA\<rbrace>, END\<rbrace>, |
230 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
230 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
231 Note that it holds for *any* set H (not just "spies evs") |
231 Note that it holds for *any* set H (not just "spies evs") |
232 satisfying the inductive hypothesis.*) |
232 satisfying the inductive hypothesis.*) |
233 lemma resp_analz_image_freshK_lemma: |
233 lemma resp_analz_image_freshK_lemma: |
234 "[| RB \<in> responses evs; |
234 "[| RB \<in> responses evs; |
235 \<forall>K KK. KK \<subseteq> - (range shrK) --> |
235 \<forall>K KK. KK \<subseteq> - (range shrK) \<longrightarrow> |
236 (Key K \<in> analz (Key`KK Un H)) = |
236 (Key K \<in> analz (Key`KK \<union> H)) = |
237 (K \<in> KK | Key K \<in> analz H) |] |
237 (K \<in> KK | Key K \<in> analz H) |] |
238 ==> \<forall>K KK. KK \<subseteq> - (range shrK) --> |
238 ==> \<forall>K KK. KK \<subseteq> - (range shrK) \<longrightarrow> |
239 (Key K \<in> analz (insert RB (Key`KK Un H))) = |
239 (Key K \<in> analz (insert RB (Key`KK \<union> H))) = |
240 (K \<in> KK | Key K \<in> analz (insert RB H))" |
240 (K \<in> KK | Key K \<in> analz (insert RB H))" |
241 apply (erule responses.induct) |
241 apply (erule responses.induct) |
242 apply (simp_all del: image_insert |
242 apply (simp_all del: image_insert |
243 add: analz_image_freshK_simps, auto) |
243 add: analz_image_freshK_simps, auto) |
244 done |
244 done |
245 |
245 |
246 |
246 |
247 text\<open>Version for the protocol. Proof is easy, thanks to the lemma.\<close> |
247 text\<open>Version for the protocol. Proof is easy, thanks to the lemma.\<close> |
248 lemma raw_analz_image_freshK: |
248 lemma raw_analz_image_freshK: |
249 "evs \<in> recur ==> |
249 "evs \<in> recur ==> |
250 \<forall>K KK. KK \<subseteq> - (range shrK) --> |
250 \<forall>K KK. KK \<subseteq> - (range shrK) \<longrightarrow> |
251 (Key K \<in> analz (Key`KK Un (spies evs))) = |
251 (Key K \<in> analz (Key`KK \<union> (spies evs))) = |
252 (K \<in> KK | Key K \<in> analz (spies evs))" |
252 (K \<in> KK | Key K \<in> analz (spies evs))" |
253 apply (erule recur.induct) |
253 apply (erule recur.induct) |
254 apply (drule_tac [4] RA2_analz_spies, |
254 apply (drule_tac [4] RA2_analz_spies, |
255 drule_tac [5] respond_imp_responses, |
255 drule_tac [5] respond_imp_responses, |
256 drule_tac [6] RA4_analz_spies, analz_freshK, spy_analz) |
256 drule_tac [6] RA4_analz_spies, analz_freshK, spy_analz) |
300 |
300 |
301 lemma unique_NA: |
301 lemma unique_NA: |
302 "[| Hash \<lbrace>Key(shrK A), Agent A, B, NA, P\<rbrace> \<in> parts (spies evs); |
302 "[| Hash \<lbrace>Key(shrK A), Agent A, B, NA, P\<rbrace> \<in> parts (spies evs); |
303 Hash \<lbrace>Key(shrK A), Agent A, B',NA, P'\<rbrace> \<in> parts (spies evs); |
303 Hash \<lbrace>Key(shrK A), Agent A, B',NA, P'\<rbrace> \<in> parts (spies evs); |
304 evs \<in> recur; A \<notin> bad |] |
304 evs \<in> recur; A \<notin> bad |] |
305 ==> B=B' & P=P'" |
305 ==> B=B' \<and> P=P'" |
306 apply (erule rev_mp, erule rev_mp) |
306 apply (erule rev_mp, erule rev_mp) |
307 apply (erule recur.induct, |
307 apply (erule recur.induct, |
308 drule_tac [5] respond_imp_responses) |
308 drule_tac [5] respond_imp_responses) |
309 apply (force, simp_all) |
309 apply (force, simp_all) |
310 txt\<open>Fake\<close> |
310 txt\<open>Fake\<close> |
320 (relations "respond" and "responses") |
320 (relations "respond" and "responses") |
321 ***) |
321 ***) |
322 |
322 |
323 lemma shrK_in_analz_respond [simp]: |
323 lemma shrK_in_analz_respond [simp]: |
324 "[| RB \<in> responses evs; evs \<in> recur |] |
324 "[| RB \<in> responses evs; evs \<in> recur |] |
325 ==> (Key (shrK B) \<in> analz (insert RB (spies evs))) = (B:bad)" |
325 ==> (Key (shrK B) \<in> analz (insert RB (spies evs))) = (B\<in>bad)" |
326 apply (erule responses.induct) |
326 apply (erule responses.induct) |
327 apply (simp_all del: image_insert |
327 apply (simp_all del: image_insert |
328 add: analz_image_freshK_simps resp_analz_image_freshK, auto) |
328 add: analz_image_freshK_simps resp_analz_image_freshK, auto) |
329 done |
329 done |
330 |
330 |
331 |
331 |
332 lemma resp_analz_insert_lemma: |
332 lemma resp_analz_insert_lemma: |
333 "[| Key K \<in> analz (insert RB H); |
333 "[| Key K \<in> analz (insert RB H); |
334 \<forall>K KK. KK \<subseteq> - (range shrK) --> |
334 \<forall>K KK. KK \<subseteq> - (range shrK) \<longrightarrow> |
335 (Key K \<in> analz (Key`KK Un H)) = |
335 (Key K \<in> analz (Key`KK \<union> H)) = |
336 (K \<in> KK | Key K \<in> analz H); |
336 (K \<in> KK | Key K \<in> analz H); |
337 RB \<in> responses evs |] |
337 RB \<in> responses evs |] |
338 ==> (Key K \<in> parts{RB} | Key K \<in> analz H)" |
338 ==> (Key K \<in> parts{RB} | Key K \<in> analz H)" |
339 apply (erule rev_mp, erule responses.induct) |
339 apply (erule rev_mp, erule responses.induct) |
340 apply (simp_all del: image_insert parts_image |
340 apply (simp_all del: image_insert parts_image |
359 possibilities. Also, the presence of two different matching messages in |
359 possibilities. Also, the presence of two different matching messages in |
360 the inductive step complicates the case analysis. Unusually for such proofs, |
360 the inductive step complicates the case analysis. Unusually for such proofs, |
361 the quantifiers appear to be necessary.*) |
361 the quantifiers appear to be necessary.*) |
362 lemma unique_lemma [rule_format]: |
362 lemma unique_lemma [rule_format]: |
363 "(PB,RB,KXY) \<in> respond evs ==> |
363 "(PB,RB,KXY) \<in> respond evs ==> |
364 \<forall>A B N. Crypt (shrK A) \<lbrace>Key K, Agent B, N\<rbrace> \<in> parts {RB} --> |
364 \<forall>A B N. Crypt (shrK A) \<lbrace>Key K, Agent B, N\<rbrace> \<in> parts {RB} \<longrightarrow> |
365 (\<forall>A' B' N'. Crypt (shrK A') \<lbrace>Key K, Agent B', N'\<rbrace> \<in> parts {RB} --> |
365 (\<forall>A' B' N'. Crypt (shrK A') \<lbrace>Key K, Agent B', N'\<rbrace> \<in> parts {RB} \<longrightarrow> |
366 (A'=A & B'=B) | (A'=B & B'=A))" |
366 (A'=A \<and> B'=B) | (A'=B \<and> B'=A))" |
367 apply (erule respond.induct) |
367 apply (erule respond.induct) |
368 apply (simp_all add: all_conj_distrib) |
368 apply (simp_all add: all_conj_distrib) |
369 apply (blast dest: respond_certificate) |
369 apply (blast dest: respond_certificate) |
370 done |
370 done |
371 |
371 |
372 lemma unique_session_keys: |
372 lemma unique_session_keys: |
373 "[| Crypt (shrK A) \<lbrace>Key K, Agent B, N\<rbrace> \<in> parts {RB}; |
373 "[| Crypt (shrK A) \<lbrace>Key K, Agent B, N\<rbrace> \<in> parts {RB}; |
374 Crypt (shrK A') \<lbrace>Key K, Agent B', N'\<rbrace> \<in> parts {RB}; |
374 Crypt (shrK A') \<lbrace>Key K, Agent B', N'\<rbrace> \<in> parts {RB}; |
375 (PB,RB,KXY) \<in> respond evs |] |
375 (PB,RB,KXY) \<in> respond evs |] |
376 ==> (A'=A & B'=B) | (A'=B & B'=A)" |
376 ==> (A'=A \<and> B'=B) | (A'=B \<and> B'=A)" |
377 by (rule unique_lemma, auto) |
377 by (rule unique_lemma, auto) |
378 |
378 |
379 |
379 |
380 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
380 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
381 Does not in itself guarantee security: an attack could violate |
381 Does not in itself guarantee security: an attack could violate |
382 the premises, e.g. by having A=Spy **) |
382 the premises, e.g. by having A=Spy **) |
383 |
383 |
384 lemma respond_Spy_not_see_session_key [rule_format]: |
384 lemma respond_Spy_not_see_session_key [rule_format]: |
385 "[| (PB,RB,KAB) \<in> respond evs; evs \<in> recur |] |
385 "[| (PB,RB,KAB) \<in> respond evs; evs \<in> recur |] |
386 ==> \<forall>A A' N. A \<notin> bad & A' \<notin> bad --> |
386 ==> \<forall>A A' N. A \<notin> bad \<and> A' \<notin> bad \<longrightarrow> |
387 Crypt (shrK A) \<lbrace>Key K, Agent A', N\<rbrace> \<in> parts{RB} --> |
387 Crypt (shrK A) \<lbrace>Key K, Agent A', N\<rbrace> \<in> parts{RB} \<longrightarrow> |
388 Key K \<notin> analz (insert RB (spies evs))" |
388 Key K \<notin> analz (insert RB (spies evs))" |
389 apply (erule respond.induct) |
389 apply (erule respond.induct) |
390 apply (frule_tac [2] respond_imp_responses) |
390 apply (frule_tac [2] respond_imp_responses) |
391 apply (frule_tac [2] respond_imp_not_used) |
391 apply (frule_tac [2] respond_imp_not_used) |
392 apply (simp_all del: image_insert parts_image |
392 apply (simp_all del: image_insert parts_image |
462 |
462 |
463 text\<open>Certificates can only originate with the Server.\<close> |
463 text\<open>Certificates can only originate with the Server.\<close> |
464 lemma Cert_imp_Server_msg: |
464 lemma Cert_imp_Server_msg: |
465 "[| Crypt (shrK A) Y \<in> parts (spies evs); |
465 "[| Crypt (shrK A) Y \<in> parts (spies evs); |
466 A \<notin> bad; evs \<in> recur |] |
466 A \<notin> bad; evs \<in> recur |] |
467 ==> \<exists>C RC. Says Server C RC \<in> set evs & |
467 ==> \<exists>C RC. Says Server C RC \<in> set evs \<and> |
468 Crypt (shrK A) Y \<in> parts {RC}" |
468 Crypt (shrK A) Y \<in> parts {RC}" |
469 apply (erule rev_mp, erule recur.induct, simp_all) |
469 apply (erule rev_mp, erule recur.induct, simp_all) |
470 txt\<open>Fake\<close> |
470 txt\<open>Fake\<close> |
471 apply blast |
471 apply blast |
472 txt\<open>RA1\<close> |
472 txt\<open>RA1\<close> |