src/HOL/Auth/Recur.ML
changeset 2516 4d68fbe6378b
parent 2485 c4368c967c56
child 2533 2d5604a51562
equal deleted inserted replaced
2515:6ff9bd353121 2516:4d68fbe6378b
     8 
     8 
     9 open Recur;
     9 open Recur;
    10 
    10 
    11 proof_timing:=true;
    11 proof_timing:=true;
    12 HOL_quantifiers := false;
    12 HOL_quantifiers := false;
    13 Pretty.setdepth 25;
    13 Pretty.setdepth 30;
    14 
    14 
    15 
    15 
    16 (** Possibility properties: traces that reach the end 
    16 (** Possibility properties: traces that reach the end 
    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 
    21 (*Simplest case: Alice goes directly to the server*)
    22 (*Simplest case: Alice goes directly to the server*)
    22 goal thy
    23 goal thy
    23  "!!A. A ~= Server   \
    24  "!!A. A ~= Server   \
    24 \ ==> EX K NA. EX evs: recur lost.          \
    25 \ ==> EX K NA. EX evs: recur lost.          \
    25 \     Says Server A {|Agent A,              \
    26 \     Says Server A {|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 (REPEAT
    32 by possibility_tac;
    33     (ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver))
       
    34      THEN
       
    35      REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI])));
       
    36 result();
    33 result();
    37 
    34 
    38 
    35 
    39 (*Case two: Alice, Bob and the server*)
    36 (*Case two: Alice, Bob and the server*)
    40 goal thy
    37 goal thy
    41  "!!A B. [| A ~= B; A ~= Server; B ~= Server |]   \
    38  "!!A B. [| A ~= B; A ~= Server; B ~= Server |]   \
    42 \ ==> EX K. EX NA. EX evs: recur lost.          \
    39 \ ==> EX K. EX NA. EX evs: recur lost.          \
    43 \       Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \
    40 \       Says B A {|Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \
    44 \                       Agent Server|}                          \
    41 \                       Agent Server|}                          \
    45 \         : set_of_list evs";
    42 \         : set_of_list evs";
       
    43 by (cut_facts_tac [Nonce_supply2, Key_supply2] 1);
       
    44 by (REPEAT (eresolve_tac [exE, conjE] 1));
    46 by (REPEAT (resolve_tac [exI,bexI] 1));
    45 by (REPEAT (resolve_tac [exI,bexI] 1));
    47 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS 
    46 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS 
    48 	  (respond.One RS respond.Cons RSN (4,recur.RA3)) RS
    47           (respond.One RS respond.Cons RSN (4,recur.RA3)) RS
    49 	  recur.RA4) 2);
    48           recur.RA4) 2);
    50 bw HPair_def;
    49 by basic_possibility_tac;
    51 by (REPEAT
    50 by (DEPTH_SOLVE (eresolve_tac [asm_rl, less_not_refl2, 
    52     (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI])
    51 			       less_not_refl2 RS not_sym] 1));
    53      THEN
       
    54      ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver))));
       
    55 result();
    52 result();
    56 
    53 
    57 
    54 
    58 (*Case three: Alice, Bob, Charlie and the server*)
    55 (*Case three: Alice, Bob, Charlie and the server
    59 goal thy
    56 goal thy
    60  "!!A B. [| A ~= B; A ~= Server; B ~= Server |]   \
    57  "!!A B. [| A ~= B; B ~= C; A ~= Server; B ~= Server; C ~= Server |]   \
    61 \ ==> EX K. EX NA. EX evs: recur lost.          \
    58 \ ==> EX K. EX NA. EX evs: recur lost.          \
    62 \       Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \
    59 \       Says B A {|Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \
    63 \                       Agent Server|}                          \
    60 \                       Agent Server|}                          \
    64 \         : set_of_list evs";
    61 \         : set_of_list evs";
       
    62 by (cut_facts_tac [Nonce_supply3, Key_supply3] 1);
       
    63 by (REPEAT (eresolve_tac [exE, conjE] 1));
    65 by (REPEAT (resolve_tac [exI,bexI] 1));
    64 by (REPEAT (resolve_tac [exI,bexI] 1));
    66 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS 
    65 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS 
    67 	  (respond.One RS respond.Cons RS respond.Cons RSN
    66           (respond.One RS respond.Cons RS respond.Cons RSN
    68 	   (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2);
    67            (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2);
    69 bw HPair_def;
    68 (*SLOW: 70 seconds*)
    70 by (REPEAT	(*SLOW: 37 seconds*)
    69 by basic_possibility_tac;
    71     (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI])
    70 by (DEPTH_SOLVE (swap_res_tac [refl, conjI, disjCI] 1 
    72      THEN
    71 		 ORELSE
    73      ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver))));
    72 		 eresolve_tac [asm_rl, less_not_refl2, 
    74 by (ALLGOALS 
    73 			       less_not_refl2 RS not_sym] 1));
    75     (SELECT_GOAL (DEPTH_SOLVE
       
    76 		  (swap_res_tac [refl, conjI, disjI1, disjI2] 1 APPEND 
       
    77 		   etac not_sym 1))));
       
    78 result();
    74 result();
    79 
    75 ****************)
    80 
       
    81 
    76 
    82 (**** Inductive proofs about recur ****)
    77 (**** Inductive proofs about recur ****)
    83 
    78 
    84 (*Monotonicity*)
    79 (*Monotonicity*)
    85 goal thy "!!evs. lost' <= lost ==> recur lost' <= recur lost";
    80 goal thy "!!evs. lost' <= lost ==> recur lost' <= recur lost";
    97 qed_spec_mp "not_Says_to_self";
    92 qed_spec_mp "not_Says_to_self";
    98 Addsimps [not_Says_to_self];
    93 Addsimps [not_Says_to_self];
    99 AddSEs   [not_Says_to_self RSN (2, rev_notE)];
    94 AddSEs   [not_Says_to_self RSN (2, rev_notE)];
   100 
    95 
   101 
    96 
       
    97 
       
    98 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> Key KAB : parts{RB}";
       
    99 by (etac respond.induct 1);
       
   100 by (ALLGOALS Simp_tac);
       
   101 qed "respond_Key_in_parts";
       
   102 
       
   103 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> Key KAB ~: used evs";
       
   104 by (etac respond.induct 1);
       
   105 by (REPEAT (assume_tac 1));
       
   106 qed "respond_imp_not_used";
       
   107 
       
   108 goal thy
       
   109  "!!evs. [| Key K : parts {RB};  (PB,RB,K') : respond evs |] \
       
   110 \        ==> Key K ~: used evs";
       
   111 by (etac rev_mp 1);
       
   112 by (etac respond.induct 1);
       
   113 by (auto_tac(!claset addDs [Key_not_used, respond_imp_not_used],
       
   114              !simpset));
       
   115 qed_spec_mp "Key_in_parts_respond";
       
   116 
   102 (*Simple inductive reasoning about responses*)
   117 (*Simple inductive reasoning about responses*)
   103 goal thy "!!j. (j,PA,RB) : respond i ==> RB : responses i";
   118 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> RB : responses evs";
   104 by (etac respond.induct 1);
   119 by (etac respond.induct 1);
   105 by (REPEAT (ares_tac responses.intrs 1));
   120 by (REPEAT (ares_tac (respond_imp_not_used::responses.intrs) 1));
   106 qed "respond_imp_responses";
   121 qed "respond_imp_responses";
   107 
   122 
   108 
   123 
   109 (** For reasoning about the encrypted portion of messages **)
   124 (** For reasoning about the encrypted portion of messages **)
   110 
   125 
   111 val RA2_analz_sees_Spy = Says_imp_sees_Spy RS analz.Inj |> standard;
   126 val RA2_analz_sees_Spy = Says_imp_sees_Spy RS analz.Inj |> standard;
   112 
   127 
   113 goal thy "!!evs. Says C' B {|Agent B, X, Agent B, X', RA|} : set_of_list evs \
   128 goal thy "!!evs. Says C' B {|X, X', RA|} : set_of_list evs \
   114 \                ==> RA : analz (sees lost Spy evs)";
   129 \                ==> RA : analz (sees lost Spy evs)";
   115 by (fast_tac (!claset addSDs [Says_imp_sees_Spy RS analz.Inj]) 1);
   130 by (fast_tac (!claset addSDs [Says_imp_sees_Spy RS analz.Inj]) 1);
   116 qed "RA4_analz_sees_Spy";
   131 qed "RA4_analz_sees_Spy";
   117 
   132 
   118 (*RA2_analz... and RA4_analz... let us treat those cases using the same 
   133 (*RA2_analz... and RA4_analz... let us treat those cases using the same 
   129   harder to complete, since simplification does less for us.*)
   144   harder to complete, since simplification does less for us.*)
   130 val parts_Fake_tac = 
   145 val parts_Fake_tac = 
   131     let val tac = forw_inst_tac [("lost","lost")] 
   146     let val tac = forw_inst_tac [("lost","lost")] 
   132     in  tac RA2_parts_sees_Spy 4              THEN
   147     in  tac RA2_parts_sees_Spy 4              THEN
   133         etac subst 4 (*RA2: DELETE needless definition of PA!*)  THEN
   148         etac subst 4 (*RA2: DELETE needless definition of PA!*)  THEN
   134 	forward_tac [respond_imp_responses] 5 THEN
   149         forward_tac [respond_imp_responses] 5 THEN
   135 	tac RA4_parts_sees_Spy 6
   150         tac RA4_parts_sees_Spy 6
   136     end;
   151     end;
   137 
   152 
   138 (*For proving the easier theorems about X ~: parts (sees lost Spy evs) *)
   153 (*For proving the easier theorems about X ~: parts (sees lost Spy evs) *)
   139 fun parts_induct_tac i = SELECT_GOAL
   154 fun parts_induct_tac i = SELECT_GOAL
   140     (DETERM (etac recur.induct 1 THEN parts_Fake_tac THEN
   155     (DETERM (etac recur.induct 1 THEN parts_Fake_tac THEN
   149 (** Theorems of the form X ~: parts (sees lost Spy evs) imply that NOBODY
   164 (** Theorems of the form X ~: parts (sees lost Spy evs) imply that NOBODY
   150     sends messages containing X! **)
   165     sends messages containing X! **)
   151 
   166 
   152 
   167 
   153 (** Spy never sees another agent's long-term key (unless initially lost) **)
   168 (** Spy never sees another agent's long-term key (unless initially lost) **)
   154 
       
   155 goal thy 
       
   156  "!!evs. (j,PB,RB) : respond i \
       
   157 \  ==> Key K : parts {RB} --> (EX j'. K = newK2(i,j') & j<=j')";
       
   158 be respond.induct 1;
       
   159 by (Auto_tac());
       
   160 by (best_tac (!claset addDs [Suc_leD]) 1);
       
   161 qed_spec_mp "Key_in_parts_respond";
       
   162 
   169 
   163 goal thy 
   170 goal thy 
   164  "!!evs. evs : recur lost \
   171  "!!evs. evs : recur lost \
   165 \        ==> (Key (shrK A) : parts (sees lost Spy evs)) = (A : lost)";
   172 \        ==> (Key (shrK A) : parts (sees lost Spy evs)) = (A : lost)";
   166 by (parts_induct_tac 1);
   173 by (parts_induct_tac 1);
   187 
   194 
   188 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D);
   195 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D);
   189 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D];
   196 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D];
   190 
   197 
   191 
   198 
   192 (*** Future keys can't be seen or used! ***)
   199 
   193 
   200 (** Nobody can have used non-existent keys! **)
   194 (*Nobody can have SEEN keys that will be generated in the future. *)
   201 
   195 goal thy "!!evs. evs : recur lost ==> \
   202 goal thy
   196 \                length evs <= i -->   \
   203  "!!evs. [| K : keysFor (parts {RB});  (PB,RB,K') : respond evs |] \
   197 \                Key (newK2(i,j)) ~: parts (sees lost Spy evs)";
   204 \        ==> K : range shrK";
   198 by (parts_induct_tac 1);
   205 by (etac rev_mp 1);
   199 (*RA2*)
   206 by (etac (respond_imp_responses RS responses.induct) 1);
   200 by (best_tac (!claset addSEs partsEs 
       
   201 	              addSDs [parts_cut]
       
   202                       addDs  [Suc_leD]
       
   203                       addss  (!simpset)) 3);
       
   204 (*Fake*)
       
   205 by (best_tac (!claset addDs [impOfSubs analz_subset_parts,
       
   206 			     impOfSubs parts_insert_subset_Un,
       
   207 			     Suc_leD]
       
   208 		      addss (!simpset)) 1);
       
   209 (*For RA3*)
       
   210 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 2);
       
   211 (*RA1-RA4*)
       
   212 by (REPEAT (best_tac (!claset addDs [Key_in_parts_respond, Suc_leD]
       
   213 		              addss (!simpset)) 1));
       
   214 qed_spec_mp "new_keys_not_seen";
       
   215 Addsimps [new_keys_not_seen];
       
   216 
       
   217 (*Variant: old messages must contain old keys!*)
       
   218 goal thy 
       
   219  "!!evs. [| Says A B X : set_of_list evs;     \
       
   220 \           Key (newK2(i,j)) : parts {X};     \
       
   221 \           evs : recur lost                 \
       
   222 \        |] ==> i < length evs";
       
   223 by (rtac ccontr 1);
       
   224 by (dtac leI 1);
       
   225 by (fast_tac (!claset addSDs [new_keys_not_seen, Says_imp_sees_Spy]
       
   226                       addIs  [impOfSubs parts_mono]) 1);
       
   227 qed "Says_imp_old_keys";
       
   228 
       
   229 
       
   230 (*** Future nonces can't be seen or used! ***)
       
   231 
       
   232 goal thy 
       
   233  "!!evs. (j, PB, RB) : respond i \
       
   234 \        ==> Nonce N : parts {RB} --> Nonce N : parts {PB}";
       
   235 be respond.induct 1;
       
   236 by (Auto_tac());
   207 by (Auto_tac());
   237 qed_spec_mp "Nonce_in_parts_respond";
   208 qed_spec_mp "Key_in_keysFor_parts";
   238 
   209 
   239 
   210 
   240 goal thy "!!i. evs : recur lost ==> \
   211 goal thy "!!evs. evs : recur lost ==>          \
   241 \              length evs <= i --> Nonce(newN i) ~: parts (sees lost Spy evs)";
   212 \       Key K ~: used evs --> K ~: keysFor (parts (sees lost Spy evs))";
   242 by (parts_induct_tac 1);
       
   243 (*For RA3*)
       
   244 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 4);
       
   245 by (deepen_tac (!claset addSDs [Says_imp_sees_Spy RS parts.Inj]
       
   246                         addDs  [Nonce_in_parts_respond, parts_cut, Suc_leD]
       
   247 			addss (!simpset)) 0 4);
       
   248 (*Fake*)
       
   249 by (fast_tac (!claset addDs  [impOfSubs analz_subset_parts,
       
   250 			      impOfSubs parts_insert_subset_Un,
       
   251 			      Suc_leD]
       
   252 		      addss (!simpset)) 1);
       
   253 (*RA1, RA2, RA4*)
       
   254 by (REPEAT_FIRST  (fast_tac (!claset 
       
   255                               addSEs partsEs
       
   256                               addEs [leD RS notE]
       
   257                               addDs [Suc_leD]
       
   258                               addss (!simpset))));
       
   259 qed_spec_mp "new_nonces_not_seen";
       
   260 Addsimps [new_nonces_not_seen];
       
   261 
       
   262 (*Variant: old messages must contain old nonces!*)
       
   263 goal thy "!!evs. [| Says A B X : set_of_list evs;    \
       
   264 \                   Nonce (newN i) : parts {X};      \
       
   265 \                   evs : recur lost                 \
       
   266 \                |] ==> i < length evs";
       
   267 by (rtac ccontr 1);
       
   268 by (dtac leI 1);
       
   269 by (fast_tac (!claset addSDs [new_nonces_not_seen, Says_imp_sees_Spy]
       
   270                       addIs  [impOfSubs parts_mono]) 1);
       
   271 qed "Says_imp_old_nonces";
       
   272 
       
   273 
       
   274 (** Nobody can have USED keys that will be generated in the future. **)
       
   275 
       
   276 goal thy
       
   277  "!!evs. (j,PB,RB) : respond i \
       
   278 \        ==> K : keysFor (parts {RB}) --> (EX A. K = shrK A)";
       
   279 be (respond_imp_responses RS responses.induct) 1;
       
   280 by (Auto_tac());
       
   281 qed_spec_mp "Key_in_keysFor_parts_respond";
       
   282 
       
   283 
       
   284 goal thy "!!i. evs : recur lost ==>          \
       
   285 \       length evs <= i --> newK2(i,j) ~: keysFor (parts (sees lost Spy evs))";
       
   286 by (parts_induct_tac 1);
   213 by (parts_induct_tac 1);
   287 (*RA3*)
   214 (*RA3*)
   288 by (fast_tac (!claset addDs  [Key_in_keysFor_parts_respond, Suc_leD]
   215 by (best_tac (!claset addDs  [Key_in_keysFor_parts]
   289 		      addss  (!simpset addsimps [parts_insert_sees])) 4);
   216                       addss  (!simpset addsimps [parts_insert_sees])) 2);
   290 (*RA2*)
   217 (*Fake*)
   291 by (fast_tac (!claset addSEs partsEs 
   218 by (best_tac
   292 	              addDs  [Suc_leD] addss (!simpset)) 3);
   219       (!claset addIs [impOfSubs analz_subset_parts]
   293 (*Fake, RA1, RA4*)
   220                addDs [impOfSubs (analz_subset_parts RS keysFor_mono),
   294 by (REPEAT 
   221                       impOfSubs (parts_insert_subset_Un RS keysFor_mono)]
   295     (best_tac
   222                addss (!simpset)) 1);
   296       (!claset addDs [impOfSubs (analz_subset_parts RS keysFor_mono),
       
   297                       impOfSubs (parts_insert_subset_Un RS keysFor_mono),
       
   298                       Suc_leD]
       
   299                addEs [new_keys_not_seen RS not_parts_not_analz RSN(2,rev_notE)]
       
   300                addss (!simpset)) 1));
       
   301 qed_spec_mp "new_keys_not_used";
   223 qed_spec_mp "new_keys_not_used";
   302 
   224 
   303 
   225 
   304 bind_thm ("new_keys_not_analzd",
   226 bind_thm ("new_keys_not_analzd",
   305           [analz_subset_parts RS keysFor_mono,
   227           [analz_subset_parts RS keysFor_mono,
   317     dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN 
   239     dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN 
   318     forward_tac [respond_imp_responses] 5                THEN
   240     forward_tac [respond_imp_responses] 5                THEN
   319     dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6;
   241     dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6;
   320 
   242 
   321 
   243 
   322 Delsimps [image_insert];
       
   323 
       
   324 (** Session keys are not used to encrypt other session keys **)
   244 (** Session keys are not used to encrypt other session keys **)
   325 
   245 
   326 (*Version for "responses" relation.  Handles case RA3 in the theorem below.  
   246 (*Version for "responses" relation.  Handles case RA3 in the theorem below.  
   327   Note that it holds for *any* set H (not just "sees lost Spy evs")
   247   Note that it holds for *any* set H (not just "sees lost Spy evs")
   328   satisfying the inductive hypothesis.*)
   248   satisfying the inductive hypothesis.*)
   329 goal thy  
   249 goal thy  
   330  "!!evs. [| RB : responses i;                             \
   250  "!!evs. [| RB : responses evs;                             \
   331 \           ALL K I. (Key K : analz (Key``(newK``I) Un H)) = \
   251 \           ALL K KK. KK <= Compl (range shrK) -->          \
   332 \           (K : newK``I | Key K : analz H) |]                \
   252 \                     (Key K : analz (Key``KK Un H)) =      \
   333 \       ==> ALL K I. (Key K : analz (insert RB (Key``(newK``I) Un H))) = \
   253 \                     (K : KK | Key K : analz H) |]         \
   334 \           (K : newK``I | Key K : analz (insert RB H))";
   254 \       ==> ALL K KK. KK <= Compl (range shrK) -->          \
   335 be responses.induct 1;
   255 \                     (Key K : analz (insert RB (Key``KK Un H))) = \
   336 by (ALLGOALS
   256 \                     (K : KK | Key K : analz (insert RB H))";
   337     (asm_simp_tac 
   257 by (etac responses.induct 1);
   338      (!simpset addsimps [insert_Key_singleton, insert_Key_image, 
   258 by (ALLGOALS (asm_simp_tac analz_image_freshK_ss));
   339 			 Un_assoc RS sym, pushKey_newK]
   259 qed "resp_analz_image_freshK_lemma";
   340                setloop split_tac [expand_if])));
       
   341 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1);
       
   342 qed "resp_analz_image_newK_lemma";
       
   343 
   260 
   344 (*Version for the protocol.  Proof is almost trivial, thanks to the lemma.*)
   261 (*Version for the protocol.  Proof is almost trivial, thanks to the lemma.*)
   345 goal thy  
   262 goal thy  
   346  "!!evs. evs : recur lost ==>                                            \
   263  "!!evs. evs : recur lost ==>                                   \
   347 \  ALL K I. (Key K : analz (Key``(newK``I) Un (sees lost Spy evs))) = \
   264 \  ALL K KK. KK <= Compl (range shrK) -->                       \
   348 \           (K : newK``I | Key K : analz (sees lost Spy evs))";
   265 \            (Key K : analz (Key``KK Un (sees lost Spy evs))) = \
       
   266 \            (K : KK | Key K : analz (sees lost Spy evs))";
   349 by (etac recur.induct 1);
   267 by (etac recur.induct 1);
   350 by analz_Fake_tac;
   268 by analz_Fake_tac;
   351 by (REPEAT_FIRST (ares_tac [allI, analz_image_newK_lemma]));
   269 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   352 by (ALLGOALS (asm_simp_tac (!simpset addsimps [resp_analz_image_newK_lemma])));
   270 by (REPEAT_FIRST (rtac analz_image_freshK_lemma ));
       
   271 by (ALLGOALS 
       
   272     (asm_simp_tac
       
   273      (analz_image_freshK_ss addsimps [resp_analz_image_freshK_lemma])));
   353 (*Base*)
   274 (*Base*)
   354 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1);
   275 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1);
   355 (*RA4, RA2, Fake*) 
   276 (*RA4, RA2, Fake*) 
   356 by (REPEAT (spy_analz_tac 1));
   277 by (REPEAT (spy_analz_tac 1));
   357 val raw_analz_image_newK = result();
   278 val raw_analz_image_freshK = result();
   358 qed_spec_mp "analz_image_newK";
   279 qed_spec_mp "analz_image_freshK";
   359 
   280 
   360 
   281 
   361 (*Instance of the lemma with H replaced by (sees lost Spy evs):
   282 (*Instance of the lemma with H replaced by (sees lost Spy evs):
   362    [| RB : responses i;  evs : recur lost |]
   283    [| RB : responses evs;  evs : recur lost; |]
   363    ==> Key xa : analz (insert RB (Key``newK``x Un sees lost Spy evs)) =
   284    ==> KK <= Compl (range shrK) --> 
   364        (xa : newK``x | Key xa : analz (insert RB (sees lost Spy evs))) 
   285        Key K : analz (insert RB (Key``KK Un sees lost Spy evs)) =
       
   286        (K : KK | Key K : analz (insert RB (sees lost Spy evs))) 
   365 *)
   287 *)
   366 bind_thm ("resp_analz_image_newK",
   288 bind_thm ("resp_analz_image_freshK",
   367 	  raw_analz_image_newK RSN
   289           raw_analz_image_freshK RSN
   368 	    (2, resp_analz_image_newK_lemma) RS spec RS spec);
   290             (2, resp_analz_image_freshK_lemma) RS spec RS spec);
   369 
   291 
   370 goal thy
   292 goal thy
   371  "!!evs. evs : recur lost ==>                               \
   293  "!!evs. [| evs : recur lost;  KAB ~: range shrK |] ==>              \
   372 \        Key K : analz (insert (Key (newK x)) (sees lost Spy evs)) = \
   294 \        Key K : analz (insert (Key KAB) (sees lost Spy evs)) =      \
   373 \        (K = newK x | Key K : analz (sees lost Spy evs))";
   295 \        (K = KAB | Key K : analz (sees lost Spy evs))";
   374 by (asm_simp_tac (HOL_ss addsimps [pushKey_newK, analz_image_newK, 
   296 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1);
   375                                    insert_Key_singleton]) 1);
   297 qed "analz_insert_freshK";
   376 by (Fast_tac 1);
   298 
   377 qed "analz_insert_Key_newK";
   299 
   378 
   300 (*Everything that's hashed is already in past traffic. *)
   379 
       
   380 (*This is more general than proving Hash_new_nonces_not_seen: we don't prove
       
   381   that "future nonces" can't be hashed, but that everything that's hashed is
       
   382   already in past traffic. *)
       
   383 goal thy "!!i. [| evs : recur lost;  A ~: lost |] ==>              \
   301 goal thy "!!i. [| evs : recur lost;  A ~: lost |] ==>              \
   384 \              Hash {|Key(shrK A), X|} : parts (sees lost Spy evs) -->  \
   302 \              Hash {|Key(shrK A), X|} : parts (sees lost Spy evs) -->  \
   385 \              X : parts (sees lost Spy evs)";
   303 \              X : parts (sees lost Spy evs)";
   386 be recur.induct 1;
   304 by (etac recur.induct 1);
   387 by parts_Fake_tac;
   305 by parts_Fake_tac;
   388 (*RA3 requires a further induction*)
   306 (*RA3 requires a further induction*)
   389 be responses.induct 5;
   307 by (etac responses.induct 5);
   390 by (ALLGOALS Asm_simp_tac);
   308 by (ALLGOALS Asm_simp_tac);
   391 (*Fake*)
   309 (*Fake*)
   392 by (best_tac (!claset addDs [impOfSubs analz_subset_parts,
   310 by (best_tac (!claset addDs [impOfSubs analz_subset_parts,
   393 			     impOfSubs Fake_parts_insert]
   311                              impOfSubs Fake_parts_insert]
   394 	              addss (!simpset addsimps [parts_insert_sees])) 2);
   312                       addss (!simpset addsimps [parts_insert_sees])) 2);
   395 (*Two others*)
   313 (*Two others*)
   396 by (REPEAT (fast_tac (!claset addss (!simpset)) 1));
   314 by (REPEAT (fast_tac (!claset addss (!simpset)) 1));
   397 bind_thm ("Hash_imp_body", result() RSN (2, rev_mp));
   315 bind_thm ("Hash_imp_body", result() RSN (2, rev_mp));
   398 
   316 
   399 
   317 
   400 (** The Nonce NA uniquely identifies A's message. 
   318 (** The Nonce NA uniquely identifies A's message. 
   401     This theorem applies to rounds RA1 and RA2!
   319     This theorem applies to steps RA1 and RA2!
   402 
   320 
   403   Unicity is not used in other proofs but is desirable in its own right.
   321   Unicity is not used in other proofs but is desirable in its own right.
   404 **)
   322 **)
   405 
   323 
   406 goal thy 
   324 goal thy 
   407  "!!evs. [| evs : recur lost; A ~: lost |]               \
   325  "!!evs. [| evs : recur lost; A ~: lost |]               \
   408 \ ==> EX B' P'. ALL B P.    \
   326 \ ==> EX B' P'. ALL B P.    \
   409 \        Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \
   327 \        Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \
   410 \          : parts (sees lost Spy evs)  -->  B=B' & P=P'";
   328 \          : parts (sees lost Spy evs)  -->  B=B' & P=P'";
   411 by (parts_induct_tac 1);
   329 by (parts_induct_tac 1);
   412 be responses.induct 3;
   330 by (etac responses.induct 3);
   413 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); 
   331 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); 
   414 by (step_tac (!claset addSEs partsEs) 1);
   332 by (step_tac (!claset addSEs partsEs) 1);
   415 (*RA1: creation of new Nonce.  Move assertion into global context*)
   333 (*RA1,2: creation of new Nonce.  Move assertion into global context*)
   416 by (expand_case_tac "NA = ?y" 1);
   334 by (ALLGOALS (expand_case_tac "NA = ?y"));
   417 by (best_tac (!claset addSIs [exI]
   335 by (REPEAT_FIRST (ares_tac [exI]));
   418                       addSDs [Hash_imp_body]
   336 by (REPEAT (best_tac (!claset addSDs [Hash_imp_body]
   419 		      addSEs (new_nonces_not_seen::partsEs)
   337                               addSEs sees_Spy_partsEs) 1));
   420 		      addss (!simpset)) 1);
       
   421 by (best_tac (!claset addss  (!simpset)) 1);
       
   422 (*RA2: creation of new Nonce*)
       
   423 by (expand_case_tac "NA = ?y" 1);
       
   424 by (best_tac (!claset addSIs [exI]
       
   425 		      addSDs [Hash_imp_body]
       
   426 		      addSEs (new_nonces_not_seen::partsEs)
       
   427 		      addss  (!simpset)) 1);
       
   428 by (best_tac (!claset addss  (!simpset)) 1);
       
   429 val lemma = result();
   338 val lemma = result();
   430 
   339 
   431 goalw thy [HPair_def]
   340 goalw thy [HPair_def]
   432  "!!evs.[| HPair (Key(shrK A)) {|Agent A, Agent B, Nonce NA, P|}   \
   341  "!!evs.[| Hash[Key(shrK A)] {|Agent A, Agent B, Nonce NA, P|}   \
   433 \            : parts (sees lost Spy evs);                          \
   342 \            : parts (sees lost Spy evs);                          \
   434 \          HPair (Key(shrK A)) {|Agent A, Agent B', Nonce NA, P'|} \
   343 \          Hash[Key(shrK A)] {|Agent A, Agent B', Nonce NA, P'|} \
   435 \            : parts (sees lost Spy evs);                          \
   344 \            : parts (sees lost Spy evs);                          \
   436 \          evs : recur lost;  A ~: lost |]                         \
   345 \          evs : recur lost;  A ~: lost |]                         \
   437 \        ==> B=B' & P=P'";
   346 \        ==> B=B' & P=P'";
   438 by (REPEAT (eresolve_tac partsEs 1));
   347 by (REPEAT (eresolve_tac partsEs 1));
   439 by (prove_unique_tac lemma 1);
   348 by (prove_unique_tac lemma 1);
   443 (*** Lemmas concerning the Server's response
   352 (*** Lemmas concerning the Server's response
   444       (relations "respond" and "responses") 
   353       (relations "respond" and "responses") 
   445 ***)
   354 ***)
   446 
   355 
   447 goal thy
   356 goal thy
   448  "!!evs. [| RB : responses i;  evs : recur lost |] \
   357  "!!evs. [| RB : responses evs;  evs : recur lost |] \
   449 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)";
   358 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)";
   450 be responses.induct 1;
   359 by (etac responses.induct 1);
   451 by (ALLGOALS
   360 by (ALLGOALS
   452     (asm_simp_tac 
   361     (asm_simp_tac 
   453      (!simpset addsimps [resp_analz_image_newK, insert_Key_singleton]
   362      (analz_image_freshK_ss addsimps [Spy_analz_shrK,
   454                setloop split_tac [expand_if])));
   363                                       resp_analz_image_freshK])));
   455 qed "shrK_in_analz_respond";
   364 qed "shrK_in_analz_respond";
   456 Addsimps [shrK_in_analz_respond];
   365 Addsimps [shrK_in_analz_respond];
   457 
   366 
   458 
   367 
   459 goal thy  
   368 goal thy  
   460  "!!evs. [| RB : responses i;                             \
   369  "!!evs. [| RB : responses evs;                             \
   461 \           ALL K I. (Key K : analz (Key``(newK``I) Un H)) = \
   370 \           ALL K KK. KK <= Compl (range shrK) -->          \
   462 \           (K : newK``I | Key K : analz H) |]                \
   371 \                     (Key K : analz (Key``KK Un H)) =      \
       
   372 \                     (K : KK | Key K : analz H) |]         \
   463 \       ==> (Key K : analz (insert RB H)) --> \
   373 \       ==> (Key K : analz (insert RB H)) --> \
   464 \                  (Key K : parts{RB} | Key K : analz H)";
   374 \           (Key K : parts{RB} | Key K : analz H)";
   465 be responses.induct 1;
   375 by (etac responses.induct 1);
   466 by (ALLGOALS
   376 by (ALLGOALS
   467     (asm_simp_tac 
   377     (asm_simp_tac 
   468      (!simpset addsimps [read_instantiate [("H", "?ff``?xx")] parts_insert,
   378      (analz_image_freshK_ss addsimps [resp_analz_image_freshK_lemma])));
   469 			 resp_analz_image_newK_lemma,
   379 (*Simplification using two distinct treatments of "image"*)
   470 			 insert_Key_singleton, insert_Key_image, 
   380 by (simp_tac (!simpset addsimps [parts_insert2]) 1);
   471 			 Un_assoc RS sym, pushKey_newK]
       
   472                setloop split_tac [expand_if])));
       
   473 (*The "Message" simpset gives the standard treatment of "image"*)
       
   474 by (simp_tac (simpset_of "Message") 1);
       
   475 by (fast_tac (!claset delrules [allE]) 1);
   381 by (fast_tac (!claset delrules [allE]) 1);
   476 qed "resp_analz_insert_lemma";
   382 qed "resp_analz_insert_lemma";
   477 
   383 
   478 bind_thm ("resp_analz_insert",
   384 bind_thm ("resp_analz_insert",
   479 	  raw_analz_image_newK RSN
   385           raw_analz_image_freshK RSN
   480 	    (2, resp_analz_insert_lemma) RSN(2, rev_mp));
   386             (2, resp_analz_insert_lemma) RSN(2, rev_mp));
   481 
   387 
   482 
   388 
   483 (*The Server does not send such messages.  This theorem lets us avoid
   389 (*The Server does not send such messages.  This theorem lets us avoid
   484   assuming B~=Server in RA4.*)
   390   assuming B~=Server in RA4.*)
   485 goal thy 
   391 goal thy 
   486  "!!evs. evs : recur lost       \
   392  "!!evs. evs : recur lost       \
   487 \ ==> ALL C X Y P. Says Server C {|X, Agent Server, Agent C, Y, P|} \
   393 \ ==> ALL C X Y P. Says Server C {|X, Agent Server, Agent C, Y, P|} \
   488 \                  ~: set_of_list evs";
   394 \                  ~: set_of_list evs";
   489 by (etac recur.induct 1);
   395 by (etac recur.induct 1);
   490 be (respond.induct) 5;
   396 by (etac (respond.induct) 5);
   491 by (Auto_tac());
   397 by (Auto_tac());
   492 qed_spec_mp "Says_Server_not";
   398 qed_spec_mp "Says_Server_not";
   493 AddSEs [Says_Server_not RSN (2,rev_notE)];
   399 AddSEs [Says_Server_not RSN (2,rev_notE)];
   494 
   400 
   495 
   401 
   496 goal thy 
   402 (*The last key returned by respond indeed appears in a certificate*)
   497  "!!i. (j,PB,RB) : respond i               \
   403 goal thy 
   498 \  ==> EX A' B'. ALL A B N.                \
   404  "!!K. (Hash[Key(shrK A)] {|Agent A, B, NA, P|}, RA, K) : respond evs \
       
   405 \ ==> Crypt (shrK A) {|Key K, B, NA|} : parts {RA}";
       
   406 by (etac respond.elim 1);
       
   407 by (ALLGOALS Asm_full_simp_tac);
       
   408 qed "respond_certificate";
       
   409 
       
   410 
       
   411 goal thy 
       
   412  "!!K'. (PB,RB,KXY) : respond evs               \
       
   413 \  ==> EX A' B'. ALL A B N.              \
   499 \        Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB} \
   414 \        Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB} \
   500 \          -->   (A'=A & B'=B) | (A'=B & B'=A)";
   415 \          -->   (A'=A & B'=B) | (A'=B & B'=A)";
   501 be respond.induct 1;
   416 by (etac respond.induct 1);
   502 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [all_conj_distrib]))); 
   417 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [all_conj_distrib]))); 
   503 (*Base case*)
   418 (*Base case*)
   504 by (Fast_tac 1);
   419 by (Fast_tac 1);
   505 by (Step_tac 1);
   420 by (Step_tac 1);
       
   421 (*Case analysis on K=KBC*)
   506 by (expand_case_tac "K = ?y" 1);
   422 by (expand_case_tac "K = ?y" 1);
       
   423 by (dtac respond_Key_in_parts 1);
   507 by (best_tac (!claset addSIs [exI]
   424 by (best_tac (!claset addSIs [exI]
   508                       addSEs partsEs
   425                       addSEs partsEs
   509                       addDs [Key_in_parts_respond]
   426                       addDs [Key_in_parts_respond]) 1);
   510                       addss (!simpset)) 1);
   427 (*Case analysis on K=KAB*)
   511 by (expand_case_tac "K = ?y" 1);
   428 by (expand_case_tac "K = ?y" 1);
   512 by (REPEAT (ares_tac [exI] 2));
   429 by (REPEAT (ares_tac [exI] 2));
   513 by (ex_strip_tac 1);
   430 by (ex_strip_tac 1);
   514 be respond.elim 1;
   431 by (dtac respond_certificate 1);
   515 by (REPEAT_FIRST (etac Pair_inject ORELSE' hyp_subst_tac));
       
   516 by (ALLGOALS (asm_full_simp_tac 
       
   517 	      (!simpset addsimps [all_conj_distrib, ex_disj_distrib]))); 
       
   518 by (Fast_tac 1);
       
   519 by (Fast_tac 1);
   432 by (Fast_tac 1);
   520 val lemma = result();
   433 val lemma = result();
   521 
   434 
   522 goal thy 
   435 goal thy 
   523  "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB};    \
   436  "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB};    \
   524 \          Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB};   \
   437 \          Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB};   \
   525 \          (j,PB,RB) : respond i |]               \
   438 \          (PB,RB,KXY) : respond evs |]               \
   526 \ ==>   (A'=A & B'=B) | (A'=B & B'=A)";
   439 \ ==>   (A'=A & B'=B) | (A'=B & B'=A)";
   527 by (prove_unique_tac lemma 1);	(*50 seconds??, due to the disjunctions*)
   440 by (prove_unique_tac lemma 1);  (*50 seconds??, due to the disjunctions*)
   528 qed "unique_session_keys";
   441 qed "unique_session_keys";
   529 
   442 
   530 
   443 
   531 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3
   444 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3
   532     Does not in itself guarantee security: an attack could violate 
   445     Does not in itself guarantee security: an attack could violate 
   533     the premises, e.g. by having A=Spy **)
   446     the premises, e.g. by having A=Spy **)
   534 
   447 
   535 goal thy 
   448 goal thy 
   536  "!!j. (j, HPair (Key(shrK A)) {|Agent A, B, NA, P|}, RA) : respond i \
   449  "!!evs. [| (PB,RB,KAB) : respond evs;  evs : recur lost |]       \
   537 \ ==> Crypt (shrK A) {|Key (newK2 (i,j)), B, NA|} : parts {RA}";
       
   538 be respond.elim 1;
       
   539 by (ALLGOALS Asm_full_simp_tac);
       
   540 qed "newK2_respond_lemma";
       
   541 
       
   542 
       
   543 goal thy 
       
   544  "!!evs. [| (j,PB,RB) : respond (length evs);  evs : recur lost |]       \
       
   545 \        ==> ALL A A' N. A ~: lost & A' ~: lost -->  \
   450 \        ==> ALL A A' N. A ~: lost & A' ~: lost -->  \
   546 \            Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} -->  \
   451 \            Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} -->  \
   547 \            Key K ~: analz (insert RB (sees lost Spy evs))";
   452 \            Key K ~: analz (insert RB (sees lost Spy evs))";
   548 be respond.induct 1;
   453 by (etac respond.induct 1);
   549 by (forward_tac [respond_imp_responses] 2);
   454 by (forward_tac [respond_imp_responses] 2);
   550 by (ALLGOALS (*4 MINUTES???*)
   455 by (forward_tac [respond_imp_not_used] 2);
       
   456 by (ALLGOALS (*43 seconds*)
   551     (asm_simp_tac 
   457     (asm_simp_tac 
   552      (!simpset addsimps 
   458      (analz_image_freshK_ss addsimps 
   553 	  ([analz_image_newK, not_parts_not_analz,
   459           [analz_image_freshK, not_parts_not_analz,
   554 	    read_instantiate [("H", "?ff``?xx")] parts_insert,
   460            shrK_in_analz_respond,
   555 	    Un_assoc RS sym, resp_analz_image_newK,
   461            read_instantiate [("H", "?ff``?xx")] parts_insert,
   556 	    insert_Key_singleton, analz_insert_Key_newK])
   462            resp_analz_image_freshK, analz_insert_freshK])));
   557       setloop split_tac [expand_if])));
   463 by (ALLGOALS Simp_tac);
   558 by (ALLGOALS (simp_tac (simpset_of "Message")));
   464 by (fast_tac (!claset addIs [impOfSubs analz_subset_parts]) 1);
   559 by (Fast_tac 1);
       
   560 by (step_tac (!claset addSEs [MPair_parts]) 1);
   465 by (step_tac (!claset addSEs [MPair_parts]) 1);
   561 (** LEVEL 6 **)
   466 (** LEVEL 7 **)
   562 by (fast_tac (!claset addDs [resp_analz_insert, Key_in_parts_respond]
   467 by (fast_tac (!claset addSDs [resp_analz_insert, Key_in_parts_respond]
   563                       addSEs [new_keys_not_seen RS not_parts_not_analz 
   468                       addDs  [impOfSubs analz_subset_parts]) 4);
   564 			      RSN(2,rev_notE)]
   469 by (fast_tac (!claset addSDs [respond_certificate]) 3);
   565                       addss (!simpset)) 4);
       
   566 by (fast_tac (!claset addSDs [newK2_respond_lemma]) 3);
       
   567 by (best_tac (!claset addSEs partsEs
   470 by (best_tac (!claset addSEs partsEs
   568                       addDs [Key_in_parts_respond]
   471                       addDs [Key_in_parts_respond]
   569                       addss (!simpset)) 2);
   472                       addss (!simpset)) 2);
   570 by (thin_tac "ALL x.?P(x)" 1);
   473 by (dtac unique_session_keys 1);
   571 be respond.elim 1;
   474 by (etac respond_certificate 1);
   572 by (fast_tac (!claset addss (!simpset)) 1);
   475 by (assume_tac 1);
   573 by (step_tac (!claset addss (!simpset)) 1);
   476 by (Fast_tac 1);
   574 by (best_tac (!claset addSEs partsEs
       
   575                       addDs [Key_in_parts_respond]
       
   576                       addss (!simpset)) 1);
       
   577 qed_spec_mp "respond_Spy_not_see_encrypted_key";
   477 qed_spec_mp "respond_Spy_not_see_encrypted_key";
   578 
   478 
   579 
   479 
   580 goal thy
   480 goal thy
   581  "!!evs. [| A ~: lost;  A' ~: lost;  evs : recur lost |]            \
   481  "!!evs. [| A ~: lost;  A' ~: lost;  evs : recur lost |]            \
   584 \            Key K ~: analz (sees lost Spy evs)";
   484 \            Key K ~: analz (sees lost Spy evs)";
   585 by (etac recur.induct 1);
   485 by (etac recur.induct 1);
   586 by analz_Fake_tac;
   486 by analz_Fake_tac;
   587 by (ALLGOALS
   487 by (ALLGOALS
   588     (asm_simp_tac
   488     (asm_simp_tac
   589      (!simpset addsimps [not_parts_not_analz, analz_insert_Key_newK] 
   489      (!simpset addsimps [not_parts_not_analz, analz_insert_freshK] 
   590                setloop split_tac [expand_if])));
   490                setloop split_tac [expand_if])));
   591 (*RA4*)
   491 (*RA4*)
   592 by (spy_analz_tac 4);
   492 by (spy_analz_tac 4);
   593 (*Fake*)
   493 (*Fake*)
   594 by (spy_analz_tac 1);
   494 by (spy_analz_tac 1);
   595 by (step_tac (!claset delrules [impCE]) 1);
   495 by (step_tac (!claset delrules [impCE]) 1);
   596 (*RA2*)
   496 (*RA2*)
   597 by (spy_analz_tac 1);
   497 by (spy_analz_tac 1);
   598 (*RA3, case 2: K is an old key*)
   498 (*RA3, case 2: K is an old key*)
   599 by (fast_tac (!claset addSDs [resp_analz_insert]
   499 by (best_tac (!claset addSDs [resp_analz_insert]
   600 		      addSEs partsEs
   500                       addSEs partsEs
   601                       addDs [Key_in_parts_respond]
   501                       addDs [Key_in_parts_respond, 
   602 	              addEs [Says_imp_old_keys RS less_irrefl]) 2);
   502                              Says_imp_sees_Spy RS parts.Inj RSN (2, parts_cut)]
       
   503                       addss (!simpset)) 2);
   603 (*RA3, case 1: use lemma previously proved by induction*)
   504 (*RA3, case 1: use lemma previously proved by induction*)
   604 by (fast_tac (!claset addSEs [respond_Spy_not_see_encrypted_key RSN
   505 by (fast_tac (!claset addSEs [respond_Spy_not_see_encrypted_key RSN
   605 			      (2,rev_notE)]) 1);
   506                               (2,rev_notE)]) 1);
   606 bind_thm ("Spy_not_see_encrypted_key", result() RS mp RSN (2, rev_mp));
   507 bind_thm ("Spy_not_see_encrypted_key", result() RS mp RSN (2, rev_mp));
   607 
   508 
   608 
   509 
   609 goal thy 
   510 goal thy 
   610  "!!evs. [| Says Server B RB : set_of_list evs;                 \
   511  "!!evs. [| Says Server B RB : set_of_list evs;                 \
   620 
   521 
   621 
   522 
   622 (**** Authenticity properties for Agents ****)
   523 (**** Authenticity properties for Agents ****)
   623 
   524 
   624 (*The response never contains Hashes*)
   525 (*The response never contains Hashes*)
   625 (*NEEDED????????????????*)
   526 goal thy
   626 goal thy
   527  "!!evs. (PB,RB,K) : respond evs \
   627  "!!evs. (j,PB,RB) : respond i \
       
   628 \        ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \
   528 \        ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \
   629 \            Hash {|Key (shrK B), M|} : parts H";
   529 \            Hash {|Key (shrK B), M|} : parts H";
   630 be (respond_imp_responses RS responses.induct) 1;
   530 by (etac (respond_imp_responses RS responses.induct) 1);
   631 by (Auto_tac());
   531 by (Auto_tac());
   632 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp));
   532 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp));
   633 
   533 
   634 (*NEEDED????????????????*)
       
   635 (*Only RA1 or RA2 can have caused such a part of a message to appear.*)
   534 (*Only RA1 or RA2 can have caused such a part of a message to appear.*)
   636 goalw thy [HPair_def]
   535 goalw thy [HPair_def]
   637  "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|}         \
   536  "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|}         \
   638 \             : parts (sees lost Spy evs);                        \
   537 \             : parts (sees lost Spy evs);                        \
   639 \            A ~: lost;  evs : recur lost |]                        \
   538 \            A ~: lost;  evs : recur lost |]                        \
   640 \        ==> Says A B (HPair (Key(shrK A)) {|Agent A, Agent B, NA, P|})  \
   539 \        ==> Says A B (Hash[Key(shrK A)] {|Agent A, Agent B, NA, P|})  \
   641 \             : set_of_list evs";
   540 \             : set_of_list evs";
   642 be rev_mp 1;
   541 by (etac rev_mp 1);
   643 by (parts_induct_tac 1);
   542 by (parts_induct_tac 1);
   644 (*RA3*)
   543 (*RA3*)
   645 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 1);
   544 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 1);
   646 qed_spec_mp "Hash_auth_sender";
   545 qed_spec_mp "Hash_auth_sender";
   647 
   546 
   648 
   547 
   649 val nonce_not_seen_now = le_refl RSN (2, new_nonces_not_seen) RSN (2,rev_notE);
   548 (** These two results subsume (for all agents) the guarantees proved
   650 
       
   651 
       
   652 (** These two results should subsume (for all agents) the guarantees proved
       
   653     separately for A and B in the Otway-Rees protocol.
   549     separately for A and B in the Otway-Rees protocol.
   654 **)
   550 **)
   655 
   551 
   656 
   552 
   657 (*Encrypted messages can only originate with the Server.*)
   553 (*Encrypted messages can only originate with the Server.*)