17 ONE theorem would be more elegant and faster! |
17 ONE theorem would be more elegant and faster! |
18 By induction on a list of agents (no repetitions) |
18 By induction on a list of agents (no repetitions) |
19 **) |
19 **) |
20 |
20 |
21 (*Simplest case: Alice goes directly to the server*) |
21 (*Simplest case: Alice goes directly to the server*) |
22 goal thy |
22 goal thy |
23 "!!A. A ~= Server \ |
23 "!!A. A ~= Server \ |
24 \ ==> EX K NA. EX evs: recur lost. \ |
24 \ ==> EX K NA. EX evs: recur lost. \ |
25 \ Says Server A {|Agent A, \ |
25 \ Says Server A {|Agent A, \ |
26 \ Crypt (shrK A) {|Key K, Agent Server, Nonce NA|}, \ |
26 \ Crypt (shrK A) {|Key K, Agent Server, Nonce NA|}, \ |
27 \ Agent Server|} \ |
27 \ Agent Server|} \ |
28 \ : set_of_list evs"; |
28 \ : set_of_list evs"; |
29 by (REPEAT (resolve_tac [exI,bexI] 1)); |
29 by (REPEAT (resolve_tac [exI,bexI] 1)); |
30 by (rtac (recur.Nil RS recur.RA1 RS |
30 by (rtac (recur.Nil RS recur.RA1 RS |
31 (respond.One RSN (4,recur.RA3))) 2); |
31 (respond.One RSN (4,recur.RA3))) 2); |
32 by (ALLGOALS (simp_tac (!simpset setsolver safe_solver))); |
32 by (REPEAT |
33 by (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI])); |
33 (ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)) |
|
34 THEN |
|
35 REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]))); |
34 result(); |
36 result(); |
35 |
37 |
36 |
38 |
37 (*Case two: Alice, Bob and the server*) |
39 (*Case two: Alice, Bob and the server*) |
38 goal thy |
40 goal thy |
39 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
41 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
40 \ ==> EX K. EX NA. EX evs: recur lost. \ |
42 \ ==> EX K. EX NA. EX evs: recur lost. \ |
41 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
43 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
42 \ Agent Server|} \ |
44 \ Agent Server|} \ |
43 \ : set_of_list evs"; |
45 \ : set_of_list evs"; |
44 by (REPEAT (resolve_tac [exI,bexI] 1)); |
46 by (REPEAT (resolve_tac [exI,bexI] 1)); |
45 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS |
47 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS |
46 (respond.One RS respond.Cons RSN (4,recur.RA3)) RS |
48 (respond.One RS respond.Cons RSN (4,recur.RA3)) RS |
47 recur.RA4) 2); |
49 recur.RA4) 2); |
|
50 bw HPair_def; |
48 by (REPEAT |
51 by (REPEAT |
49 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
52 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
50 THEN |
53 THEN |
51 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
54 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
52 result(); |
55 result(); |
53 |
56 |
54 |
57 |
55 (*Case three: Alice, Bob, Charlie and the server*) |
58 (*Case three: Alice, Bob, Charlie and the server*) |
56 goal thy |
59 goal thy |
57 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
60 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
58 \ ==> EX K. EX NA. EX evs: recur lost. \ |
61 \ ==> EX K. EX NA. EX evs: recur lost. \ |
59 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
62 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
60 \ Agent Server|} \ |
63 \ Agent Server|} \ |
61 \ : set_of_list evs"; |
64 \ : set_of_list evs"; |
62 by (REPEAT (resolve_tac [exI,bexI] 1)); |
65 by (REPEAT (resolve_tac [exI,bexI] 1)); |
63 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS |
66 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS |
64 (respond.One RS respond.Cons RS respond.Cons RSN |
67 (respond.One RS respond.Cons RS respond.Cons RSN |
65 (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2); |
68 (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2); |
|
69 bw HPair_def; |
66 by (REPEAT (*SLOW: 37 seconds*) |
70 by (REPEAT (*SLOW: 37 seconds*) |
67 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
71 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
68 THEN |
72 THEN |
69 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
73 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
70 by (ALLGOALS |
74 by (ALLGOALS |
311 dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN |
315 dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN |
312 forward_tac [respond_imp_responses] 5 THEN |
316 forward_tac [respond_imp_responses] 5 THEN |
313 dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6; |
317 dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6; |
314 |
318 |
315 |
319 |
|
320 Delsimps [image_insert]; |
|
321 |
316 (** Session keys are not used to encrypt other session keys **) |
322 (** Session keys are not used to encrypt other session keys **) |
317 |
323 |
318 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
324 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
319 Note that it holds for *any* set H (not just "sees lost Spy evs") |
325 Note that it holds for *any* set H (not just "sees lost Spy evs") |
320 satisfying the inductive hypothesis.*) |
326 satisfying the inductive hypothesis.*) |
337 goal thy |
343 goal thy |
338 "!!evs. evs : recur lost ==> \ |
344 "!!evs. evs : recur lost ==> \ |
339 \ ALL K I. (Key K : analz (Key``(newK``I) Un (sees lost Spy evs))) = \ |
345 \ ALL K I. (Key K : analz (Key``(newK``I) Un (sees lost Spy evs))) = \ |
340 \ (K : newK``I | Key K : analz (sees lost Spy evs))"; |
346 \ (K : newK``I | Key K : analz (sees lost Spy evs))"; |
341 by (etac recur.induct 1); |
347 by (etac recur.induct 1); |
|
348 be subst 4; (*RA2: DELETE needless definition of PA!*) |
342 by analz_Fake_tac; |
349 by analz_Fake_tac; |
343 be ssubst 4; (*RA2: DELETE needless definition of PA!*) |
|
344 by (REPEAT_FIRST (ares_tac [allI, analz_image_newK_lemma])); |
350 by (REPEAT_FIRST (ares_tac [allI, analz_image_newK_lemma])); |
345 by (ALLGOALS (asm_simp_tac (!simpset addsimps [resp_analz_image_newK_lemma]))); |
351 by (ALLGOALS (asm_simp_tac (!simpset addsimps [resp_analz_image_newK_lemma]))); |
346 (*Base*) |
352 (*Base*) |
347 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1); |
353 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1); |
348 (*RA4, RA2, Fake*) |
354 (*RA4, RA2, Fake*) |
414 "!!evs. [| evs : recur lost; A ~: lost |] \ |
420 "!!evs. [| evs : recur lost; A ~: lost |] \ |
415 \ ==> EX B' P'. ALL B P. \ |
421 \ ==> EX B' P'. ALL B P. \ |
416 \ Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \ |
422 \ Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \ |
417 \ : parts (sees lost Spy evs) --> B=B' & P=P'"; |
423 \ : parts (sees lost Spy evs) --> B=B' & P=P'"; |
418 be recur.induct 1; |
424 be recur.induct 1; |
419 be ssubst 4; (*RA2: DELETE needless definition of PA!*) |
425 be subst 4; (*RA2: DELETE needless definition of PA!*) |
420 (*For better simplification of RA2*) |
426 (*For better simplification of RA2*) |
421 by (res_inst_tac [("x1","XA")] (insert_commute RS ssubst) 4); |
427 by (res_inst_tac [("x1","XA")] (insert_commute RS ssubst) 4); |
422 by parts_Fake_tac; |
428 by parts_Fake_tac; |
423 (*RA3 requires a further induction*) |
429 (*RA3 requires a further induction*) |
424 be responses.induct 5; |
430 be responses.induct 5; |
429 (*Fake*) |
435 (*Fake*) |
430 by (best_tac (!claset addSIs [exI] |
436 by (best_tac (!claset addSIs [exI] |
431 addDs [impOfSubs analz_subset_parts, |
437 addDs [impOfSubs analz_subset_parts, |
432 impOfSubs Fake_parts_insert] |
438 impOfSubs Fake_parts_insert] |
433 addss (!simpset)) 2); |
439 addss (!simpset)) 2); |
434 (*Base*) |
440 (*Base*) (** LEVEL 9 **) |
435 by (fast_tac (!claset addss (!simpset)) 1); |
441 by (fast_tac (!claset addss (!simpset)) 1); |
436 |
|
437 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); |
442 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); |
438 (*RA1: creation of new Nonce. Move assertion into global context*) |
443 (*RA1: creation of new Nonce. Move assertion into global context*) |
439 by (expand_case_tac "NA = ?y" 1); |
444 by (expand_case_tac "NA = ?y" 1); |
440 by (best_tac (!claset addSIs [exI] |
445 by (best_tac (!claset addSIs [exI] |
441 addEs [Hash_new_nonces_not_seen] |
446 addEs [Hash_new_nonces_not_seen] |
448 addEs [Hash_new_nonces_not_seen] |
453 addEs [Hash_new_nonces_not_seen] |
449 addss (!simpset)) 1); |
454 addss (!simpset)) 1); |
450 by (best_tac (!claset addss (!simpset)) 1); |
455 by (best_tac (!claset addss (!simpset)) 1); |
451 val lemma = result(); |
456 val lemma = result(); |
452 |
457 |
453 goal thy |
458 goalw thy [HPair_def] |
454 "!!evs.[| Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \ |
459 "!!evs.[| HPair (Key(shrK A)) {|Agent A, Agent B, Nonce NA, P|} \ |
455 \ : parts (sees lost Spy evs); \ |
460 \ : parts (sees lost Spy evs); \ |
456 \ Hash {|Key(shrK A), Agent A, Agent B', Nonce NA, P'|} \ |
461 \ HPair (Key(shrK A)) {|Agent A, Agent B', Nonce NA, P'|} \ |
457 \ : parts (sees lost Spy evs); \ |
462 \ : parts (sees lost Spy evs); \ |
458 \ evs : recur lost; A ~: lost |] \ |
463 \ evs : recur lost; A ~: lost |] \ |
459 \ ==> B=B' & P=P'"; |
464 \ ==> B=B' & P=P'"; |
|
465 by (REPEAT (eresolve_tac partsEs 1)); |
460 by (prove_unique_tac lemma 1); |
466 by (prove_unique_tac lemma 1); |
461 qed "unique_NA"; |
467 qed "unique_NA"; |
462 |
468 |
463 |
469 |
464 (*** Lemmas concerning the Server's response |
470 (*** Lemmas concerning the Server's response |
465 (relations "respond" and "responses") |
471 (relations "respond" and "responses") |
466 ***) |
472 ***) |
467 |
|
468 (*The response never contains Hashes*) |
|
469 (*NEEDED????????????????*) |
|
470 goal thy |
|
471 "!!evs. (j,PB,RB) : respond i \ |
|
472 \ ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \ |
|
473 \ Hash {|Key (shrK B), M|} : parts H"; |
|
474 be (respond_imp_responses RS responses.induct) 1; |
|
475 by (Auto_tac()); |
|
476 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp)); |
|
477 |
|
478 |
473 |
479 goal thy |
474 goal thy |
480 "!!evs. [| RB : responses i; evs : recur lost |] \ |
475 "!!evs. [| RB : responses i; evs : recur lost |] \ |
481 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)"; |
476 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)"; |
482 be responses.induct 1; |
477 be responses.induct 1; |
554 goal thy |
549 goal thy |
555 "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB}; \ |
550 "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB}; \ |
556 \ Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB}; \ |
551 \ Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB}; \ |
557 \ (j,PB,RB) : respond i |] \ |
552 \ (j,PB,RB) : respond i |] \ |
558 \ ==> (A'=A & B'=B) | (A'=B & B'=A)"; |
553 \ ==> (A'=A & B'=B) | (A'=B & B'=A)"; |
559 by (prove_unique_tac lemma 1); (*33 seconds, due to the disjunctions*) |
554 by (prove_unique_tac lemma 1); (*50 seconds??, due to the disjunctions*) |
560 qed "unique_session_keys"; |
555 qed "unique_session_keys"; |
561 |
556 |
562 |
557 |
563 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
558 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
564 Does not in itself guarantee security: an attack could violate |
559 Does not in itself guarantee security: an attack could violate |
565 the premises, e.g. by having A=Spy **) |
560 the premises, e.g. by having A=Spy **) |
566 |
561 |
567 goal thy |
562 goal thy |
568 "!!j. (j, {|Hash {|Key(shrK A), Agent A, B, NA, P|}, X|}, RA) : respond i \ |
563 "!!j. (j, HPair (Key(shrK A)) {|Agent A, B, NA, P|}, RA) : respond i \ |
569 \ ==> Crypt (shrK A) {|Key (newK2 (i,j)), B, NA|} : parts {RA}"; |
564 \ ==> Crypt (shrK A) {|Key (newK2 (i,j)), B, NA|} : parts {RA}"; |
570 be respond.elim 1; |
565 be respond.elim 1; |
571 by (ALLGOALS Asm_full_simp_tac); |
566 by (ALLGOALS Asm_full_simp_tac); |
572 qed "newK2_respond_lemma"; |
567 qed "newK2_respond_lemma"; |
573 |
568 |
577 \ ==> ALL A A' N. A ~: lost & A' ~: lost --> \ |
572 \ ==> ALL A A' N. A ~: lost & A' ~: lost --> \ |
578 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
573 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
579 \ Key K ~: analz (insert RB (sees lost Spy evs))"; |
574 \ Key K ~: analz (insert RB (sees lost Spy evs))"; |
580 be respond.induct 1; |
575 be respond.induct 1; |
581 by (forward_tac [respond_imp_responses] 2); |
576 by (forward_tac [respond_imp_responses] 2); |
582 by (ALLGOALS |
577 by (ALLGOALS (*4 MINUTES???*) |
583 (asm_simp_tac |
578 (asm_simp_tac |
584 (!simpset addsimps |
579 (!simpset addsimps |
585 ([analz_image_newK, not_parts_not_analz, |
580 ([analz_image_newK, not_parts_not_analz, |
586 read_instantiate [("H", "?ff``?xx")] parts_insert, |
581 read_instantiate [("H", "?ff``?xx")] parts_insert, |
587 Un_assoc RS sym, resp_analz_image_newK, |
582 Un_assoc RS sym, resp_analz_image_newK, |
613 "!!evs. [| A ~: lost; A' ~: lost; evs : recur lost |] \ |
608 "!!evs. [| A ~: lost; A' ~: lost; evs : recur lost |] \ |
614 \ ==> Says Server B RB : set_of_list evs --> \ |
609 \ ==> Says Server B RB : set_of_list evs --> \ |
615 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
610 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
616 \ Key K ~: analz (sees lost Spy evs)"; |
611 \ Key K ~: analz (sees lost Spy evs)"; |
617 by (etac recur.induct 1); |
612 by (etac recur.induct 1); |
|
613 be subst 4; (*RA2: DELETE needless definition of PA!*) |
618 by analz_Fake_tac; |
614 by analz_Fake_tac; |
619 be ssubst 4; (*RA2: DELETE needless definition of PA!*) |
|
620 by (ALLGOALS |
615 by (ALLGOALS |
621 (asm_simp_tac |
616 (asm_simp_tac |
622 (!simpset addsimps [not_parts_not_analz, analz_insert_Key_newK] |
617 (!simpset addsimps [not_parts_not_analz, analz_insert_Key_newK] |
623 setloop split_tac [expand_if]))); |
618 setloop split_tac [expand_if]))); |
624 (*RA4*) |
619 (*RA4*) |
652 qed "Agent_not_see_encrypted_key"; |
647 qed "Agent_not_see_encrypted_key"; |
653 |
648 |
654 |
649 |
655 (**** Authenticity properties for Agents ****) |
650 (**** Authenticity properties for Agents ****) |
656 |
651 |
|
652 (*The response never contains Hashes*) |
|
653 (*NEEDED????????????????*) |
|
654 goal thy |
|
655 "!!evs. (j,PB,RB) : respond i \ |
|
656 \ ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \ |
|
657 \ Hash {|Key (shrK B), M|} : parts H"; |
|
658 be (respond_imp_responses RS responses.induct) 1; |
|
659 by (Auto_tac()); |
|
660 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp)); |
|
661 |
657 (*NEEDED????????????????*) |
662 (*NEEDED????????????????*) |
658 (*Only RA1 or RA2 can have caused such a part of a message to appear.*) |
663 (*Only RA1 or RA2 can have caused such a part of a message to appear.*) |
659 goal thy |
664 goalw thy [HPair_def] |
660 "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|} \ |
665 "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|} \ |
661 \ : parts (sees lost Spy evs); \ |
666 \ : parts (sees lost Spy evs); \ |
662 \ A ~: lost; evs : recur lost |] \ |
667 \ A ~: lost; evs : recur lost |] \ |
663 \ ==> Says A B {|Hash{|Key(shrK A), Agent A, Agent B, NA, P|}, \ |
668 \ ==> Says A B (HPair (Key(shrK A)) {|Agent A, Agent B, NA, P|}) \ |
664 \ Agent A, Agent B, NA, P|} \ |
|
665 \ : set_of_list evs"; |
669 \ : set_of_list evs"; |
666 be rev_mp 1; |
670 be rev_mp 1; |
667 by (parts_induct_tac 1); |
671 by (parts_induct_tac 1); |
668 (*RA3*) |
672 (*RA3*) |
669 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 2); |
673 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 2); |
672 (res_inst_tac [("x1","XA")] (insert_commute RS ssubst) 1)); |
676 (res_inst_tac [("x1","XA")] (insert_commute RS ssubst) 1)); |
673 by (best_tac (!claset addSEs partsEs |
677 by (best_tac (!claset addSEs partsEs |
674 addDs [parts_cut] |
678 addDs [parts_cut] |
675 addss (!simpset)) 1); |
679 addss (!simpset)) 1); |
676 qed_spec_mp "Hash_auth_sender"; |
680 qed_spec_mp "Hash_auth_sender"; |
677 |
|
678 |
|
679 (*NEEDED????????????????*) |
|
680 goal thy "!!i. {|Hash {|Key (shrK Server), M|}, M|} : responses i ==> R"; |
|
681 be setup_induction 1; |
|
682 be responses.induct 1; |
|
683 by (ALLGOALS Asm_simp_tac); |
|
684 qed "responses_no_Hash_Server"; |
|
685 |
681 |
686 |
682 |
687 val nonce_not_seen_now = le_refl RSN (2, new_nonces_not_seen) RSN (2,rev_notE); |
683 val nonce_not_seen_now = le_refl RSN (2, new_nonces_not_seen) RSN (2,rev_notE); |
688 |
684 |
689 |
685 |