src/HOL/Auth/Yahalom.ML
changeset 1995 c80e58e78d9c
parent 1985 84cf16192e03
child 2001 974167c1d2c4
equal deleted inserted replaced
1994:4ddfafdeefa4 1995:c80e58e78d9c
     1 (*  Title:      HOL/Auth/OtwayRees
     1 (*  Title:      HOL/Auth/Yahalom
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     3     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     4     Copyright   1996  University of Cambridge
     4     Copyright   1996  University of Cambridge
     5 
     5 
     6 Inductive relation "otway" for the Yahalom protocol.
     6 Inductive relation "otway" for the Yahalom protocol.
     8 From page 257 of
     8 From page 257 of
     9   Burrows, Abadi and Needham.  A Logic of Authentication.
     9   Burrows, Abadi and Needham.  A Logic of Authentication.
    10   Proc. Royal Soc. 426 (1989)
    10   Proc. Royal Soc. 426 (1989)
    11 *)
    11 *)
    12 
    12 
    13 open OtwayRees;
    13 open Yahalom;
    14 
    14 
    15 proof_timing:=true;
    15 proof_timing:=true;
    16 HOL_quantifiers := false;
    16 HOL_quantifiers := false;
       
    17 
       
    18 
       
    19 (** Weak liveness: there are traces that reach the end **)
       
    20 
       
    21 goal thy 
       
    22  "!!A B. [| A ~= B; A ~= Server; B ~= Server |]   \
       
    23 \        ==> EX X NB K. EX evs: yahalom.          \
       
    24 \               Says A B {|X, Crypt (Nonce NB) K|} : set_of_list evs";
       
    25 by (REPEAT (resolve_tac [exI,bexI] 1));
       
    26 br (yahalom.Nil RS yahalom.YM1 RS yahalom.YM2 RS yahalom.YM3 RS yahalom.YM4) 2;
       
    27 by (ALLGOALS (simp_tac (!simpset setsolver safe_solver)));
       
    28 by (ALLGOALS Fast_tac);
       
    29 qed "weak_liveness";
       
    30 
    17 
    31 
    18 (**** Inductive proofs about yahalom ****)
    32 (**** Inductive proofs about yahalom ****)
    19 
    33 
    20 (*The Enemy can see more than anybody else, except for their initial state*)
    34 (*The Enemy can see more than anybody else, except for their initial state*)
    21 goal thy 
    35 goal thy 
    43 AddSEs   [not_Notes RSN (2, rev_notE)];
    57 AddSEs   [not_Notes RSN (2, rev_notE)];
    44 
    58 
    45 
    59 
    46 (** For reasoning about the encrypted portion of messages **)
    60 (** For reasoning about the encrypted portion of messages **)
    47 
    61 
    48 goal thy "!!evs. (Says A' B {|N, Agent A, Agent B, X|}) : set_of_list evs ==> \
    62 (*Lets us treat YM4 using a similar argument as for the Fake case.*)
    49 \                X : analz (sees Enemy evs)";
    63 goal thy "!!evs. Says S A {|Crypt Y (shrK A), X|} : set_of_list evs ==> \
    50 by (fast_tac (!claset addSDs [Says_imp_sees_Enemy RS analz.Inj]) 1);
       
    51 qed "YM2_analz_sees_Enemy";
       
    52 
       
    53 goal thy "!!evs. (Says S B {|N, X, X'|}) : set_of_list evs ==> \
       
    54 \                X : analz (sees Enemy evs)";
    64 \                X : analz (sees Enemy evs)";
    55 by (fast_tac (!claset addSDs [Says_imp_sees_Enemy RS analz.Inj]) 1);
    65 by (fast_tac (!claset addSDs [Says_imp_sees_Enemy RS analz.Inj]) 1);
    56 qed "YM4_analz_sees_Enemy";
    66 qed "YM4_analz_sees_Enemy";
    57 
    67 
    58 goal thy "!!evs. (Says B' A {|N, Crypt {|N,K|} K'|}) : set_of_list evs ==> \
    68 goal thy "!!evs. Says S A {|Crypt {|B, K, NA, NB|} (shrK A), X|} \
       
    69 \                  : set_of_list evs ==> \
    59 \                K : parts (sees Enemy evs)";
    70 \                K : parts (sees Enemy evs)";
    60 by (fast_tac (!claset addSEs partsEs
    71 by (fast_tac (!claset addSEs partsEs
    61 	              addSDs [Says_imp_sees_Enemy RS parts.Inj]) 1);
    72 	              addSDs [Says_imp_sees_Enemy RS parts.Inj]) 1);
    62 qed "YM5_parts_sees_Enemy";
    73 qed "YM4_parts_sees_Enemy";
    63 
    74 
    64 (*YM2_analz... and YM4_analz... let us treat those cases using the same 
       
    65   argument as for the Fake case.  This is possible for most, but not all,
       
    66   proofs: Fake does not invent new nonces (as in YM2), and of course Fake
       
    67   messages originate from the Enemy. *)
       
    68 
       
    69 val YM2_YM4_tac = 
       
    70     dtac (YM2_analz_sees_Enemy RS (impOfSubs analz_subset_parts)) 4 THEN
       
    71     dtac (YM4_analz_sees_Enemy RS (impOfSubs analz_subset_parts)) 6;
       
    72 
    75 
    73 
    76 
    74 (*** Shared keys are not betrayed ***)
    77 (*** Shared keys are not betrayed ***)
    75 
    78 
    76 (*Enemy never sees another agent's shared key! (unless it is leaked at start)*)
    79 (*Enemy never sees another agent's shared key! (unless it is leaked at start)*)
    77 goal thy 
    80 goal thy 
    78  "!!evs. [| evs : yahalom;  A ~: bad |] ==> \
    81  "!!evs. [| evs : yahalom;  A ~: bad |] ==> \
    79 \        Key (shrK A) ~: parts (sees Enemy evs)";
    82 \        Key (shrK A) ~: parts (sees Enemy evs)";
    80 be yahalom.induct 1;
    83 be yahalom.induct 1;
    81 by YM2_YM4_tac;
    84 bd (YM4_analz_sees_Enemy RS synth.Inj) 6;
       
    85 by (ALLGOALS Asm_simp_tac);
       
    86 by (stac insert_commute 3);
    82 by (Auto_tac());
    87 by (Auto_tac());
    83 (*Deals with Fake message*)
    88 (*Fake and YM4 are similar*)
    84 by (best_tac (!claset addDs [impOfSubs analz_subset_parts,
    89 by (ALLGOALS (best_tac (!claset addSDs [impOfSubs analz_subset_parts,
    85 			     impOfSubs Fake_parts_insert]) 1);
    90 					impOfSubs Fake_parts_insert])));
    86 qed "Enemy_not_see_shrK";
    91 qed "Enemy_not_see_shrK";
    87 
    92 
    88 bind_thm ("Enemy_not_analz_shrK",
    93 bind_thm ("Enemy_not_analz_shrK",
    89 	  [analz_subset_parts, Enemy_not_see_shrK] MRS contra_subsetD);
    94 	  [analz_subset_parts, Enemy_not_see_shrK] MRS contra_subsetD);
    90 
    95 
    92 
    97 
    93 (*We go to some trouble to preserve R in the 3rd and 4th subgoals
    98 (*We go to some trouble to preserve R in the 3rd and 4th subgoals
    94   As usual fast_tac cannot be used because it uses the equalities too soon*)
    99   As usual fast_tac cannot be used because it uses the equalities too soon*)
    95 val major::prems = 
   100 val major::prems = 
    96 goal thy  "[| Key (shrK A) : parts (sees Enemy evs);       \
   101 goal thy  "[| Key (shrK A) : parts (sees Enemy evs);       \
    97 \             evs : yahalom;                                 \
   102 \             evs : yahalom;                               \
    98 \             A:bad ==> R                                  \
   103 \             A:bad ==> R                                  \
    99 \           |] ==> R";
   104 \           |] ==> R";
   100 br ccontr 1;
   105 br ccontr 1;
   101 br ([major, Enemy_not_see_shrK] MRS rev_notE) 1;
   106 br ([major, Enemy_not_see_shrK] MRS rev_notE) 1;
   102 by (swap_res_tac prems 2);
   107 by (swap_res_tac prems 2);
   119   induction! *)
   124   induction! *)
   120 goal thy "!!evs. evs : yahalom ==> \
   125 goal thy "!!evs. evs : yahalom ==> \
   121 \                length evs <= length evs' --> \
   126 \                length evs <= length evs' --> \
   122 \                          Key (newK evs') ~: (UN C. parts (sees C evs))";
   127 \                          Key (newK evs') ~: (UN C. parts (sees C evs))";
   123 be yahalom.induct 1;
   128 be yahalom.induct 1;
   124 by YM2_YM4_tac;
   129 bd (YM4_analz_sees_Enemy RS synth.Inj) 6;
   125 (*auto_tac does not work here, as it performs safe_tac first*)
       
   126 by (ALLGOALS Asm_simp_tac);
       
   127 by (REPEAT_FIRST (best_tac (!claset addDs [impOfSubs analz_subset_parts,
   130 by (REPEAT_FIRST (best_tac (!claset addDs [impOfSubs analz_subset_parts,
   128 				       impOfSubs parts_insert_subset_Un,
   131 					   impOfSubs parts_insert_subset_Un,
   129 				       Suc_leD]
   132 					   Suc_leD]
   130 			        addss (!simpset))));
   133 			            addss (!simpset))));
   131 val lemma = result();
   134 val lemma = result();
   132 
   135 
   133 (*Variant needed for the main theorem below*)
   136 (*Variant needed for the main theorem below*)
   134 goal thy 
   137 goal thy 
   135  "!!evs. [| evs : yahalom;  length evs <= length evs' |] ==> \
   138  "!!evs. [| evs : yahalom;  length evs <= length evs' |] ==> \
   154   ...very like new_keys_not_seen*)
   157   ...very like new_keys_not_seen*)
   155 goal thy "!!evs. evs : yahalom ==> \
   158 goal thy "!!evs. evs : yahalom ==> \
   156 \                length evs <= length evs' --> \
   159 \                length evs <= length evs' --> \
   157 \                newK evs' ~: keysFor (UN C. parts (sees C evs))";
   160 \                newK evs' ~: keysFor (UN C. parts (sees C evs))";
   158 be yahalom.induct 1;
   161 be yahalom.induct 1;
   159 by YM2_YM4_tac;
   162 by (forward_tac [YM4_parts_sees_Enemy] 6);
   160 bd YM5_parts_sees_Enemy 7;
   163 bd (YM4_analz_sees_Enemy RS synth.Inj) 6;
   161 by (ALLGOALS Asm_simp_tac);
   164 by (ALLGOALS Asm_full_simp_tac);
   162 (*YM1 and YM3*)
   165 (*YM1, YM2 and YM3*)
   163 by (EVERY (map (fast_tac (!claset addDs [Suc_leD] addss (!simpset))) [4,2]));
   166 by (EVERY (map (fast_tac (!claset addDs [Suc_leD] addss (!simpset))) [4,3,2]));
   164 (*Fake, YM2, YM4: these messages send unknown (X) components*)
   167 (*Fake and YM4: these messages send unknown (X) components*)
   165 by (EVERY 
   168 by (stac insert_commute 2);
   166     (map
   169 by (Simp_tac 2);
       
   170 (*YM4: the only way K could have been used is if it had been seen,
       
   171   contradicting new_keys_not_seen*)
       
   172 by (ALLGOALS
   167      (best_tac
   173      (best_tac
   168       (!claset addSDs [newK_invKey]
   174       (!claset addDs [impOfSubs (analz_subset_parts RS keysFor_mono),
   169 	       addDs [impOfSubs (analz_subset_parts RS keysFor_mono),
       
   170 		      impOfSubs (parts_insert_subset_Un RS keysFor_mono),
   175 		      impOfSubs (parts_insert_subset_Un RS keysFor_mono),
   171 		      Suc_leD]
   176 		      Suc_leD]
   172 	       addEs [new_keys_not_seen RS not_parts_not_analz RSN(2,rev_notE)]
   177 	       addDs [impOfSubs analz_subset_parts]
   173 	       addss (!simpset)))
   178 	       addEs [new_keys_not_seen RSN(2,rev_notE)]
   174      [3,2,1]));
   179 	       addss (!simpset))));
   175 (*YM5: dummy message*)
       
   176 by (best_tac (!claset addSDs [newK_invKey]
       
   177 		        addEs  [new_keys_not_seen RSN(2,rev_notE)]
       
   178 			addIs  [less_SucI, impOfSubs keysFor_mono]
       
   179 			addss (!simpset addsimps [le_def])) 1);
       
   180 val lemma = result();
   180 val lemma = result();
   181 
   181 
   182 goal thy 
   182 goal thy 
   183  "!!evs. [| evs : yahalom;  length evs <= length evs' |] ==> \
   183  "!!evs. [| evs : yahalom;  length evs <= length evs' |] ==> \
   184 \        newK evs' ~: keysFor (parts (sees C evs))";
   184 \        newK evs' ~: keysFor (parts (sees C evs))";
   212 goal thy 
   212 goal thy 
   213  "!!evs. evs : yahalom ==> \
   213  "!!evs. evs : yahalom ==> \
   214 \        (Crypt X (newK evt)) : parts (sees Enemy evs) & \
   214 \        (Crypt X (newK evt)) : parts (sees Enemy evs) & \
   215 \        Key K : parts {X} --> Key K : parts (sees Enemy evs)";
   215 \        Key K : parts {X} --> Key K : parts (sees Enemy evs)";
   216 be yahalom.induct 1;
   216 be yahalom.induct 1;
   217 by YM2_YM4_tac;
   217 bd (YM4_analz_sees_Enemy RS synth.Inj) 6;
   218 by (ALLGOALS (asm_simp_tac (!simpset addsimps pushes)));
   218 by (ALLGOALS (asm_simp_tac (!simpset addsimps pushes)));
   219 (*Deals with Faked messages*)
   219 (*Deals with Faked messages*)
   220 by (best_tac (!claset addSEs partsEs
   220 by (EVERY 
   221 		      addDs [impOfSubs analz_subset_parts,
   221     (map (best_tac (!claset addSEs partsEs
   222                              impOfSubs parts_insert_subset_Un]
   222 			    addDs [impOfSubs analz_subset_parts,
   223                       addss (!simpset)) 2);
   223 				   impOfSubs parts_insert_subset_Un]
   224 (*Base case and YM5*)
   224 			    addss (!simpset)))
       
   225      [3,2]));
       
   226 (*Base case*)
   225 by (Auto_tac());
   227 by (Auto_tac());
   226 result();
   228 result();
   227 
   229 
   228 
   230 
   229 (** Specialized rewriting for this proof **)
   231 (** Specialized rewriting for this proof **)
   257 
   259 
   258 
   260 
   259 
   261 
   260 (** Session keys are not used to encrypt other session keys **)
   262 (** Session keys are not used to encrypt other session keys **)
   261 
   263 
   262 (*Could generalize this so that the X component doesn't have to be first
       
   263   in the message?*)
       
   264 val enemy_analz_tac =
       
   265   SELECT_GOAL 
       
   266    (EVERY [REPEAT (resolve_tac [impI,notI] 1),
       
   267 	   dtac (impOfSubs Fake_analz_insert) 1,
       
   268 	   eresolve_tac [asm_rl, synth.Inj] 1,
       
   269 	   Fast_tac 1,
       
   270 	   Asm_full_simp_tac 1,
       
   271 	   IF_UNSOLVED (deepen_tac (!claset addIs [impOfSubs analz_mono]) 0 1)
       
   272 	   ]);
       
   273 
       
   274 
       
   275 (*Lemma for the trivial direction of the if-and-only-if*)
   264 (*Lemma for the trivial direction of the if-and-only-if*)
   276 goal thy  
   265 goal thy  
   277  "!!evs. (Key K : analz (Key``nE Un sEe)) --> \
   266  "!!evs. (Key K : analz (Key``nE Un sEe)) --> \
   278 \         (K : nE | Key K : analz sEe)  ==>     \
   267 \         (K : nE | Key K : analz sEe)  ==>     \
   279 \        (Key K : analz (Key``nE Un sEe)) = (K : nE | Key K : analz sEe)";
   268 \        (Key K : analz (Key``nE Un sEe)) = (K : nE | Key K : analz sEe)";
   284 goal thy  
   273 goal thy  
   285  "!!evs. evs : yahalom ==> \
   274  "!!evs. evs : yahalom ==> \
   286 \  ALL K E. (Key K : analz (Key``(newK``E) Un (sees Enemy evs))) = \
   275 \  ALL K E. (Key K : analz (Key``(newK``E) Un (sees Enemy evs))) = \
   287 \           (K : newK``E | Key K : analz (sees Enemy evs))";
   276 \           (K : newK``E | Key K : analz (sees Enemy evs))";
   288 be yahalom.induct 1;
   277 be yahalom.induct 1;
   289 bd YM2_analz_sees_Enemy 4;
       
   290 bd YM4_analz_sees_Enemy 6;
   278 bd YM4_analz_sees_Enemy 6;
   291 by (REPEAT_FIRST (resolve_tac [allI, lemma]));
   279 by (REPEAT_FIRST (resolve_tac [allI, lemma]));
   292 by (ALLGOALS (*Takes 35 secs*)
   280 by (ALLGOALS 
   293     (asm_simp_tac 
   281     (asm_simp_tac 
   294      (!simpset addsimps ([insert_Key_singleton, insert_Key_image, pushKey_newK]
   282      (!simpset addsimps ([insert_Key_singleton, insert_Key_image, pushKey_newK]
   295 			 @ pushes)
   283 			 @ pushes)
   296                setloop split_tac [expand_if])));
   284                setloop split_tac [expand_if])));
   297 (*YM4*) 
   285 (*YM4*) 
   298 by (enemy_analz_tac 5);
   286 by (enemy_analz_tac 4);
   299 (*YM3*)
   287 (*YM3*)
   300 by (Fast_tac 4);
   288 by (Fast_tac 3);
   301 (*YM2*) (** LEVEL 7 **)
   289 (*Fake case*)
   302 by (res_inst_tac [("x1","X"), ("y1", "{|?XX,?YY|}")] 
       
   303     (insert_commute RS ssubst) 3);
       
   304 by (res_inst_tac [("x1","X"), ("y1", "{|?XX,?YY|}")]
       
   305     (insert_commute RS ssubst) 3);
       
   306 by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 3);
       
   307 by (enemy_analz_tac 3);
       
   308 (*Fake case*) (** LEVEL 11 **)
       
   309 by (res_inst_tac [("y1","X"), ("A1", "?G Un (?H::msg set)")] 
       
   310     (insert_commute RS ssubst) 2);
       
   311 by (enemy_analz_tac 2);
   290 by (enemy_analz_tac 2);
   312 (*Base case*)
   291 (*Base case*)
   313 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1);
   292 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1);
   314 qed_spec_mp "analz_image_newK";
   293 qed_spec_mp "analz_image_newK";
   315 
       
   316 
   294 
   317 goal thy
   295 goal thy
   318  "!!evs. evs : yahalom ==>                               \
   296  "!!evs. evs : yahalom ==>                               \
   319 \        Key K : analz (insert (Key (newK evt)) (sees Enemy evs)) = \
   297 \        Key K : analz (insert (Key (newK evt)) (sees Enemy evs)) = \
   320 \        (K = newK evt | Key K : analz (sees Enemy evs))";
   298 \        (K = newK evt | Key K : analz (sees Enemy evs))";
   324 qed "analz_insert_Key_newK";
   302 qed "analz_insert_Key_newK";
   325 
   303 
   326 
   304 
   327 (*Describes the form *and age* of K when the following message is sent*)
   305 (*Describes the form *and age* of K when the following message is sent*)
   328 goal thy 
   306 goal thy 
   329  "!!evs. [| Says Server B \
   307  "!!evs. [| Says Server A                                           \
   330 \            {|NA, Crypt {|NA, K|} (shrK A),                      \
   308 \            {|Crypt {|Agent B, K, NA, NB|} (shrK A),               \
   331 \                  Crypt {|NB, K|} (shrK B)|} : set_of_list evs;  \
   309 \              Crypt {|Agent A, K|} (shrK B)|} : set_of_list evs;   \
   332 \           evs : yahalom |]                                        \
   310 \           evs : yahalom |]                                        \
   333 \        ==> (EX evt:yahalom. K = Key(newK evt) & \
   311 \        ==> (EX evt:yahalom. K = Key(newK evt) &                   \
   334 \                           length evt < length evs) &            \
   312 \                           length evt < length evs)";
   335 \            (EX i. NA = Nonce i)";
       
   336 be rev_mp 1;
   313 be rev_mp 1;
   337 be yahalom.induct 1;
   314 be yahalom.induct 1;
   338 by (ALLGOALS (fast_tac (!claset addIs [less_SucI] addss (!simpset))));
   315 by (ALLGOALS (fast_tac (!claset addIs [less_SucI] addss (!simpset))));
   339 qed "Says_Server_message_form";
   316 qed "Says_Server_message_form";
   340 
   317 
   341 
   318 
   342 (*Crucial secrecy property: Enemy does not see the keys sent in msg YM3*)
   319 (*Crucial secrecy property: Enemy does not see the keys sent in msg YM3
       
   320   As with Otway-Rees, proof does not need uniqueness of session keys.*)
   343 goal thy 
   321 goal thy 
   344  "!!evs. [| Says Server A \
   322  "!!evs. [| Says Server A \
   345 \            {|NA, Crypt {|NA, K|} (shrK B),                      \
   323 \            {|Crypt {|Agent B, K, NA, NB|} (shrK A),                   \
   346 \                  Crypt {|NB, K|} (shrK A)|} : set_of_list evs;  \
   324 \              Crypt {|Agent A, K|} (shrK B)|} : set_of_list evs;       \
   347 \           A ~: bad;  B ~: bad;  evs : yahalom |] ==>              \
   325 \           A ~: bad;  B ~: bad;  evs : yahalom |] ==>                  \
   348 \     K ~: analz (sees Enemy evs)";
   326 \     K ~: analz (sees Enemy evs)";
   349 be rev_mp 1;
   327 be rev_mp 1;
   350 be yahalom.induct 1;
   328 be yahalom.induct 1;
   351 bd YM2_analz_sees_Enemy 4;
       
   352 bd YM4_analz_sees_Enemy 6;
   329 bd YM4_analz_sees_Enemy 6;
   353 by (ALLGOALS Asm_simp_tac);
   330 by (ALLGOALS Asm_simp_tac);
   354 (*Next 3 steps infer that K has the form "Key (newK evs'" ... *)
   331 (*Next 3 steps infer that K has the form "Key (newK evs'" ... *)
   355 by (REPEAT_FIRST (resolve_tac [conjI, impI]));
   332 by (REPEAT_FIRST (resolve_tac [conjI, impI]));
   356 by (TRYALL (forward_tac [Says_Server_message_form] THEN' assume_tac));
   333 by (TRYALL (forward_tac [Says_Server_message_form] THEN' assume_tac));
   358 by (ALLGOALS
   335 by (ALLGOALS
   359     (asm_full_simp_tac 
   336     (asm_full_simp_tac 
   360      (!simpset addsimps ([analz_subset_parts RS contra_subsetD,
   337      (!simpset addsimps ([analz_subset_parts RS contra_subsetD,
   361 			  analz_insert_Key_newK] @ pushes)
   338 			  analz_insert_Key_newK] @ pushes)
   362                setloop split_tac [expand_if])));
   339                setloop split_tac [expand_if])));
       
   340 (*YM4*)
       
   341 by (enemy_analz_tac 3);
   363 (*YM3*)
   342 (*YM3*)
   364 by (fast_tac (!claset addSEs [less_irrefl]) 3);
   343 by (fast_tac (!claset addSEs [less_irrefl]) 2);
   365 (*Fake*) (** LEVEL 10 **)
   344 (*Fake*) (** LEVEL 10 **)
   366 by (res_inst_tac [("y1","X"), ("x1", "Key ?K")] (insert_commute RS ssubst) 1);
       
   367 by (enemy_analz_tac 1);
       
   368 (*YM4*)
       
   369 by (mp_tac 2);
       
   370 by (enemy_analz_tac 2);
       
   371 (*YM2*)
       
   372 by (mp_tac 1);
       
   373 by (res_inst_tac [("x1","X"), ("y1", "{|?XX,?YY|}")]
       
   374     (insert_commute RS ssubst) 1);
       
   375 by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1);
       
   376 by (enemy_analz_tac 1);
   345 by (enemy_analz_tac 1);
   377 qed "Enemy_not_see_encrypted_key";
   346 qed "Enemy_not_see_encrypted_key";
   378 
       
   379 
       
   380 
       
   381 (*** Session keys are issued at most once, and identify the principals ***)
       
   382 
       
   383 (** First, two lemmas for the Fake, YM2 and YM4 cases **)
       
   384 
       
   385 goal thy 
       
   386  "!!evs. [| X : synth (analz (sees Enemy evs));                \
       
   387 \           Crypt X' (shrK C) : parts{X};                      \
       
   388 \           C ~: bad;  evs : yahalom |]  \
       
   389 \        ==> Crypt X' (shrK C) : parts (sees Enemy evs)";
       
   390 by (best_tac (!claset addSEs [impOfSubs analz_subset_parts]
       
   391 	              addDs [impOfSubs parts_insert_subset_Un]
       
   392                       addss (!simpset)) 1);
       
   393 qed "Crypt_Fake_parts";
       
   394 
       
   395 goal thy 
       
   396  "!!evs. [| Crypt X' K : parts (sees A evs);  evs : yahalom |]  \
       
   397 \        ==> EX S S' Y. Says S S' Y : set_of_list evs &       \
       
   398 \            Crypt X' K : parts {Y}";
       
   399 bd parts_singleton 1;
       
   400 by (fast_tac (!claset addSDs [seesD] addss (!simpset)) 1);
       
   401 qed "Crypt_parts_singleton";
       
   402 
       
   403 fun ex_strip_tac i = REPEAT (ares_tac [exI, conjI] i) THEN assume_tac (i+1);
       
   404 
       
   405 (*The Key K uniquely identifies a pair of senders in the message encrypted by
       
   406   C, but if C=Enemy then he could send all sorts of nonsense.*)
       
   407 goal thy 
       
   408  "!!evs. evs : yahalom ==>                                     \
       
   409 \      EX A B. ALL C.                                        \
       
   410 \         C ~: bad -->                                       \
       
   411 \         (ALL S S' X. Says S S' X : set_of_list evs -->     \
       
   412 \           (EX NA. Crypt {|NA, Key K|} (shrK C) : parts{X}) --> C=A | C=B)";
       
   413 by (Simp_tac 1);
       
   414 be yahalom.induct 1;
       
   415 bd YM2_analz_sees_Enemy 4;
       
   416 bd YM4_analz_sees_Enemy 6;
       
   417 by (ALLGOALS 
       
   418     (asm_simp_tac (!simpset addsimps [all_conj_distrib, imp_conj_distrib])));
       
   419 by (REPEAT_FIRST (etac exE));
       
   420 (*YM4*)
       
   421 by (ex_strip_tac 4);
       
   422 by (fast_tac (!claset addSDs [synth.Inj RS Crypt_Fake_parts, 
       
   423 			      Crypt_parts_singleton]) 4);
       
   424 (*YM3: Case split propagates some context to other subgoal...*)
       
   425 	(** LEVEL 8 **)
       
   426 by (excluded_middle_tac "K = newK evsa" 3);
       
   427 by (Asm_simp_tac 3);
       
   428 by (REPEAT (ares_tac [exI] 3));
       
   429 (*...we prove this case by contradiction: the key is too new!*)
       
   430 by (fast_tac (!claset addIs [impOfSubs (subset_insertI RS parts_mono)]
       
   431 		      addSEs partsEs
       
   432 		      addEs [Says_imp_old_keys RS less_irrefl]
       
   433 	              addss (!simpset)) 3);
       
   434 (*YM2*) (** LEVEL 12 **)
       
   435 by (ex_strip_tac 2);
       
   436 by (res_inst_tac [("x1","X"), ("y1", "{|?XX,?YY|}")]
       
   437     (insert_commute RS ssubst) 2);
       
   438 by (Simp_tac 2);
       
   439 by (fast_tac (!claset addSDs [synth.Inj RS Crypt_Fake_parts, 
       
   440 			      Crypt_parts_singleton]) 2);
       
   441 (*Fake*) (** LEVEL 16 **)
       
   442 by (ex_strip_tac 1);
       
   443 by (fast_tac (!claset addSDs [Crypt_Fake_parts, Crypt_parts_singleton]) 1);
       
   444 qed "unique_session_keys";
       
   445 
       
   446 (*It seems strange but this theorem is NOT needed to prove the main result!*)