src/HOL/Auth/TLS.ML
changeset 5433 b66a23a45377
parent 5421 01fc8d6a40f2
child 5535 678999604ee9
equal deleted inserted replaced
5432:983b9bf8e89f 5433:b66a23a45377
    14 
    14 
    15 * Each party who has received a FINISHED message can trust that the other
    15 * Each party who has received a FINISHED message can trust that the other
    16   party agrees on all message components, including PA and PB (thus foiling
    16   party agrees on all message components, including PA and PB (thus foiling
    17   rollback attacks).
    17   rollback attacks).
    18 *)
    18 *)
       
    19 
       
    20 AddEs spies_partsEs;
       
    21 AddDs [impOfSubs analz_subset_parts];
       
    22 AddDs [impOfSubs Fake_parts_insert];
    19 
    23 
    20 (*Automatically unfold the definition of "certificate"*)
    24 (*Automatically unfold the definition of "certificate"*)
    21 Addsimps [certificate_def];
    25 Addsimps [certificate_def];
    22 
    26 
    23 (*Injectiveness of key-generating functions*)
    27 (*Injectiveness of key-generating functions*)
    59 
    63 
    60 
    64 
    61 (*Possibility property ending with ClientAccepts.*)
    65 (*Possibility property ending with ClientAccepts.*)
    62 Goal "[| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
    66 Goal "[| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
    63 \        A ~= B |]            \
    67 \        A ~= B |]            \
    64 \  ==> EX SID M. EX evs: tls.    \
    68 \     ==> EX SID M. EX evs: tls.    \
    65 \     Notes A {|Number SID, Agent A, Agent B, Nonce M|} : set evs";
    69 \          Notes A {|Number SID, Agent A, Agent B, Nonce M|} : set evs";
    66 by (REPEAT (resolve_tac [exI,bexI] 1));
    70 by (REPEAT (resolve_tac [exI,bexI] 1));
    67 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.Certificate RS
    71 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.Certificate RS
    68 	  tls.ClientKeyExch RS tls.ClientFinished RS tls.ServerFinished RS
    72 	  tls.ClientKeyExch RS tls.ClientFinished RS tls.ServerFinished RS
    69 	  tls.ClientAccepts) 2);
    73 	  tls.ClientAccepts) 2);
    70 by possibility_tac;
    74 by possibility_tac;
    72 result();
    76 result();
    73 
    77 
    74 (*And one for ServerAccepts.  Either FINISHED message may come first.*)
    78 (*And one for ServerAccepts.  Either FINISHED message may come first.*)
    75 Goal "[| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
    79 Goal "[| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
    76 \        A ~= B |]                        \
    80 \        A ~= B |]                        \
    77 \  ==> EX SID NA PA NB PB M. EX evs: tls.    \
    81 \     ==> EX SID NA PA NB PB M. EX evs: tls.    \
    78 \     Notes B {|Number SID, Agent A, Agent B, Nonce M|} : set evs";
    82 \          Notes B {|Number SID, Agent A, Agent B, Nonce M|} : set evs";
    79 by (REPEAT (resolve_tac [exI,bexI] 1));
    83 by (REPEAT (resolve_tac [exI,bexI] 1));
    80 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.Certificate RS
    84 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.Certificate RS
    81 	  tls.ClientKeyExch RS tls.ServerFinished RS tls.ClientFinished RS
    85 	  tls.ClientKeyExch RS tls.ServerFinished RS tls.ClientFinished RS
    82 	  tls.ServerAccepts) 2);
    86 	  tls.ServerAccepts) 2);
    83 by possibility_tac;
    87 by possibility_tac;
    99 (*Another one, for session resumption (both ServerResume and ClientResume) *)
   103 (*Another one, for session resumption (both ServerResume and ClientResume) *)
   100 Goal "[| evs0 : tls;     \
   104 Goal "[| evs0 : tls;     \
   101 \        Notes A {|Number SID, Agent A, Agent B, Nonce M|} : set evs0; \
   105 \        Notes A {|Number SID, Agent A, Agent B, Nonce M|} : set evs0; \
   102 \        Notes B {|Number SID, Agent A, Agent B, Nonce M|} : set evs0; \
   106 \        Notes B {|Number SID, Agent A, Agent B, Nonce M|} : set evs0; \
   103 \        ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
   107 \        ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF;  \
   104 \        A ~= B |] ==> EX NA PA NB PB X. EX evs: tls.    \
   108 \        A ~= B |] \
   105 \   X = Hash{|Number SID, Nonce M,             \
   109 \     ==> EX NA PA NB PB X. EX evs: tls.    \
   106 \                    Nonce NA, Number PA, Agent A,      \
   110 \           X = Hash{|Number SID, Nonce M,             \
   107 \                    Nonce NB, Number PB, Agent B|}  &  \
   111 \                     Nonce NA, Number PA, Agent A,      \
   108 \   Says A B (Crypt (clientK(NA,NB,M)) X) : set evs  &  \
   112 \                     Nonce NB, Number PB, Agent B|}  &  \
   109 \   Says B A (Crypt (serverK(NA,NB,M)) X) : set evs";
   113 \           Says A B (Crypt (clientK(NA,NB,M)) X) : set evs  &  \
       
   114 \           Says B A (Crypt (serverK(NA,NB,M)) X) : set evs";
   110 by (REPEAT (resolve_tac [exI,bexI] 1));
   115 by (REPEAT (resolve_tac [exI,bexI] 1));
   111 by (etac (tls.ClientHello RS tls.ServerHello RS tls.ServerResume RS 
   116 by (etac (tls.ClientHello RS tls.ServerHello RS tls.ServerResume RS 
   112 	  tls.ClientResume) 2);
   117 	  tls.ClientResume) 2);
   113 by possibility_tac;
   118 by possibility_tac;
   114 by (REPEAT (Blast_tac 1));
   119 by (REPEAT (Blast_tac 1));
   115 result();
   120 result();
   116 
   121 
   117 
   122 
   118 
   123 
   119 (**** Inductive proofs about tls ****)
   124 (**** Inductive proofs about tls ****)
   120 
       
   121 (*Nobody sends themselves messages*)
       
   122 Goal "evs : tls ==> ALL X. Says A A X ~: set evs";
       
   123 by (etac tls.induct 1);
       
   124 by Auto_tac;
       
   125 qed_spec_mp "not_Says_to_self";
       
   126 Addsimps [not_Says_to_self];
       
   127 AddSEs   [not_Says_to_self RSN (2, rev_notE)];
       
   128 
   125 
   129 
   126 
   130 (*Induction for regularity theorems.  If induction formula has the form
   127 (*Induction for regularity theorems.  If induction formula has the form
   131    X ~: analz (spies evs) --> ... then it shortens the proof by discarding
   128    X ~: analz (spies evs) --> ... then it shortens the proof by discarding
   132    needless information about analz (insert X (spies evs))  *)
   129    needless information about analz (insert X (spies evs))  *)
   143     sends messages containing X! **)
   140     sends messages containing X! **)
   144 
   141 
   145 (*Spy never sees another agent's private key! (unless it's bad at start)*)
   142 (*Spy never sees another agent's private key! (unless it's bad at start)*)
   146 Goal "evs : tls ==> (Key (priK A) : parts (spies evs)) = (A : bad)";
   143 Goal "evs : tls ==> (Key (priK A) : parts (spies evs)) = (A : bad)";
   147 by (parts_induct_tac 1);
   144 by (parts_induct_tac 1);
   148 by (Fake_parts_insert_tac 1);
   145 by (Blast_tac 1);
   149 qed "Spy_see_priK";
   146 qed "Spy_see_priK";
   150 Addsimps [Spy_see_priK];
   147 Addsimps [Spy_see_priK];
   151 
   148 
   152 Goal "evs : tls ==> (Key (priK A) : analz (spies evs)) = (A : bad)";
   149 Goal "evs : tls ==> (Key (priK A) : analz (spies evs)) = (A : bad)";
   153 by (auto_tac(claset() addDs [impOfSubs analz_subset_parts], simpset()));
   150 by Auto_tac;
   154 qed "Spy_analz_priK";
   151 qed "Spy_analz_priK";
   155 Addsimps [Spy_analz_priK];
   152 Addsimps [Spy_analz_priK];
   156 
   153 
   157 AddSDs [Spy_see_priK RSN (2, rev_iffD1), 
   154 AddSDs [Spy_see_priK RSN (2, rev_iffD1), 
   158 	Spy_analz_priK RSN (2, rev_iffD1)];
   155 	Spy_analz_priK RSN (2, rev_iffD1)];
   164   breach of security.*)
   161   breach of security.*)
   165 Goalw [certificate_def]
   162 Goalw [certificate_def]
   166     "[| certificate B KB : parts (spies evs);  evs : tls |] ==> pubK B = KB";
   163     "[| certificate B KB : parts (spies evs);  evs : tls |] ==> pubK B = KB";
   167 by (etac rev_mp 1);
   164 by (etac rev_mp 1);
   168 by (parts_induct_tac 1);
   165 by (parts_induct_tac 1);
   169 by (Fake_parts_insert_tac 1);
   166 by (Blast_tac 1);
   170 qed "certificate_valid";
   167 qed "certificate_valid";
   171 
   168 
   172 
   169 
   173 (*Replace key KB in ClientKeyExch by (pubK B) *)
   170 (*Replace key KB in ClientKeyExch by (pubK B) *)
   174 val ClientKeyExch_tac = 
   171 val ClientKeyExch_tac = 
   206 by (parts_induct_tac 1);
   203 by (parts_induct_tac 1);
   207 by (ALLGOALS Clarify_tac);
   204 by (ALLGOALS Clarify_tac);
   208 (*Fake*)
   205 (*Fake*)
   209 by (blast_tac (claset() addIs [parts_insertI]) 1);
   206 by (blast_tac (claset() addIs [parts_insertI]) 1);
   210 (*Client, Server Accept*)
   207 (*Client, Server Accept*)
   211 by (REPEAT (blast_tac (claset() addSEs spies_partsEs
   208 by (REPEAT (blast_tac (claset() addSDs [Notes_Crypt_parts_spies]) 1));
   212                                 addSDs [Notes_Crypt_parts_spies]) 1));
       
   213 qed "Notes_master_imp_Crypt_PMS";
   209 qed "Notes_master_imp_Crypt_PMS";
   214 
   210 
   215 (*Compared with the theorem above, both premise and conclusion are stronger*)
   211 (*Compared with the theorem above, both premise and conclusion are stronger*)
   216 Goal "[| Notes A {|s, Agent A, Agent B, Nonce(PRF(PMS,NA,NB))|} : set evs;\
   212 Goal "[| Notes A {|s, Agent A, Agent B, Nonce(PRF(PMS,NA,NB))|} : set evs;\
   217 \        evs : tls |]    \
   213 \        evs : tls |]    \
   231 \        evs : tls;  A ~: bad |]                         \
   227 \        evs : tls;  A ~: bad |]                         \
   232 \     ==> Says A B X : set evs";
   228 \     ==> Says A B X : set evs";
   233 by (etac rev_mp 1);
   229 by (etac rev_mp 1);
   234 by (hyp_subst_tac 1);
   230 by (hyp_subst_tac 1);
   235 by (parts_induct_tac 1);
   231 by (parts_induct_tac 1);
   236 by (Fake_parts_insert_tac 1);
   232 by (Blast_tac 1);
   237 val lemma = result();
   233 val lemma = result();
   238 
   234 
   239 (*Final version: B checks X using the distributed KA instead of priK A*)
   235 (*Final version: B checks X using the distributed KA instead of priK A*)
   240 Goal "[| X : parts (spies evs);                            \
   236 Goal "[| X : parts (spies evs);                            \
   241 \        X = Crypt (invKey KA) (Hash{|nb, Agent B, pms|}); \
   237 \        X = Crypt (invKey KA) (Hash{|nb, Agent B, pms|}); \
   251 \          : parts (spies evs);                          \
   247 \          : parts (spies evs);                          \
   252 \        evs : tls;  A ~: bad |]                         \
   248 \        evs : tls;  A ~: bad |]                         \
   253 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs";
   249 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs";
   254 by (etac rev_mp 1);
   250 by (etac rev_mp 1);
   255 by (parts_induct_tac 1);
   251 by (parts_induct_tac 1);
   256 by (Fake_parts_insert_tac 1);
   252 by (Blast_tac 1);
   257 val lemma = result();
   253 val lemma = result();
   258 
   254 
   259 (*Final version using the distributed KA instead of priK A*)
   255 (*Final version using the distributed KA instead of priK A*)
   260 Goal "[| Crypt (invKey KA) (Hash{|nb, Agent B, Nonce PMS|}) \
   256 Goal "[| Crypt (invKey KA) (Hash{|nb, Agent B, Nonce PMS|}) \
   261 \          : parts (spies evs);                             \
   257 \          : parts (spies evs);                             \
   276 
   272 
   277 Goal "[| Nonce (PRF (PMS,NA,NB)) : parts (spies evs);  evs : tls |]  \
   273 Goal "[| Nonce (PRF (PMS,NA,NB)) : parts (spies evs);  evs : tls |]  \
   278 \     ==> Nonce PMS : parts (spies evs)";
   274 \     ==> Nonce PMS : parts (spies evs)";
   279 by (etac rev_mp 1);
   275 by (etac rev_mp 1);
   280 by (parts_induct_tac 1);
   276 by (parts_induct_tac 1);
   281 by (Fake_parts_insert_tac 1);
   277 (*Easy, e.g. by freshness*)
   282 (*SpyKeys*)
   278 by (REPEAT (blast_tac (claset() addDs [Notes_Crypt_parts_spies]) 2));
   283 by (blast_tac (claset() addDs [impOfSubs analz_subset_parts]) 1);
   279 (*Fake*)
   284 (*Six others, all trivial or by freshness*)
   280 by (blast_tac (claset() addIs [parts_insertI]) 1);
   285 by (REPEAT (blast_tac (claset() addSDs [Notes_Crypt_parts_spies]
       
   286                                 addSEs spies_partsEs) 1));
       
   287 qed "MS_imp_PMS";
   281 qed "MS_imp_PMS";
   288 AddSDs [MS_imp_PMS];
   282 AddSDs [MS_imp_PMS];
   289 
   283 
   290 
   284 
   291 
   285 
   295 Goal "[| Nonce PMS ~: analz (spies evs);  evs : tls |]   \
   289 Goal "[| Nonce PMS ~: analz (spies evs);  evs : tls |]   \
   296 \     ==> EX B'. ALL B.   \
   290 \     ==> EX B'. ALL B.   \
   297 \           Crypt (pubK B) (Nonce PMS) : parts (spies evs) --> B=B'";
   291 \           Crypt (pubK B) (Nonce PMS) : parts (spies evs) --> B=B'";
   298 by (etac rev_mp 1);
   292 by (etac rev_mp 1);
   299 by (parts_induct_tac 1);
   293 by (parts_induct_tac 1);
   300 by (Fake_parts_insert_tac 1);
   294 by (Blast_tac 1);
   301 (*ClientKeyExch*)
   295 (*ClientKeyExch*)
   302 by (ClientKeyExch_tac 1);
   296 by (ClientKeyExch_tac 1);
   303 by (asm_simp_tac (simpset() addsimps [all_conj_distrib]) 1);
   297 by (asm_simp_tac (simpset() addsimps [all_conj_distrib]) 1);
   304 by (expand_case_tac "PMS = ?y" 1 THEN
   298 by (expand_case_tac "PMS = ?y" 1 THEN
   305     blast_tac (claset() addSEs partsEs) 1);
   299     blast_tac (claset() addSEs partsEs) 1);
   413 \  ==> Key K ~: parts (spies evs) & (ALL Y. Crypt K Y ~: parts (spies evs))";
   407 \  ==> Key K ~: parts (spies evs) & (ALL Y. Crypt K Y ~: parts (spies evs))";
   414 by (etac rev_mp 1);
   408 by (etac rev_mp 1);
   415 by (hyp_subst_tac 1);
   409 by (hyp_subst_tac 1);
   416 by (analz_induct_tac 1);
   410 by (analz_induct_tac 1);
   417 (*SpyKeys*)
   411 (*SpyKeys*)
   418 by (blast_tac (claset() addDs [impOfSubs analz_subset_parts]) 3);
   412 by (Blast_tac 3);
   419 (*Fake*)
   413 (*Fake*)
   420 by (Fake_parts_insert_tac 2);
   414 by (blast_tac (claset() addIs [parts_insertI]) 2);
   421 (** LEVEL 6 **)
   415 (** LEVEL 6 **)
   422 (*Oops*)
   416 (*Oops*)
   423 by (fast_tac (claset() addSEs [MPair_parts]
   417 by (Force_tac 6);
   424 		       addDs  [Says_imp_spies RS parts.Inj]
       
   425 		       addss (simpset())) 6);
       
   426 by (REPEAT 
   418 by (REPEAT 
   427     (blast_tac (claset() addSDs [Notes_Crypt_parts_spies, 
   419     (blast_tac (claset() addSDs [Notes_Crypt_parts_spies, 
   428 				 Notes_master_imp_Crypt_PMS]
   420 				 Notes_master_imp_Crypt_PMS]) 1));
   429                          addSEs spies_partsEs) 1));
       
   430 val lemma = result();
   421 val lemma = result();
   431 
   422 
   432 Goal "[| Key (sessionK((Na, Nb, PRF(PMS,NA,NB)), b)) : parts (spies evs); \
   423 Goal "[| Key (sessionK((Na, Nb, PRF(PMS,NA,NB)), b)) : parts (spies evs); \
   433 \        evs : tls |]             \
   424 \        evs : tls |]             \
   434 \     ==> Nonce PMS : parts (spies evs)";
   425 \     ==> Nonce PMS : parts (spies evs)";
   439 \          : parts (spies evs);  evs : tls |]             \
   430 \          : parts (spies evs);  evs : tls |]             \
   440 \     ==> Nonce PMS : parts (spies evs)";
   431 \     ==> Nonce PMS : parts (spies evs)";
   441 by (blast_tac (claset() addDs [lemma]) 1);
   432 by (blast_tac (claset() addDs [lemma]) 1);
   442 qed "PMS_Crypt_sessionK_not_spied";
   433 qed "PMS_Crypt_sessionK_not_spied";
   443 
   434 
   444 (*Lemma: write keys are never sent if M (MASTER SECRET) is secure.  
   435 (*Write keys are never sent if M (MASTER SECRET) is secure.  
   445   Converse doesn't hold; betraying M doesn't force the keys to be sent!
   436   Converse fails; betraying M doesn't force the keys to be sent!
   446   The strong Oops condition can be weakened later by unicity reasoning, 
   437   The strong Oops condition can be weakened later by unicity reasoning, 
   447 	with some effort.*)
   438   with some effort.  
       
   439   NO LONGER USED: see clientK_not_spied and serverK_not_spied*)
   448 Goal "[| ALL A. Says A Spy (Key (sessionK((NA,NB,M),b))) ~: set evs; \
   440 Goal "[| ALL A. Says A Spy (Key (sessionK((NA,NB,M),b))) ~: set evs; \
   449 \        Nonce M ~: analz (spies evs);  evs : tls |]   \
   441 \        Nonce M ~: analz (spies evs);  evs : tls |]   \
   450 \     ==> Key (sessionK((NA,NB,M),b)) ~: parts (spies evs)";
   442 \     ==> Key (sessionK((NA,NB,M),b)) ~: parts (spies evs)";
   451 by (etac rev_mp 1);
   443 by (etac rev_mp 1);
   452 by (etac rev_mp 1);
   444 by (etac rev_mp 1);
   453 by (analz_induct_tac 1);        (*17 seconds*)
   445 by (analz_induct_tac 1);        (*7 seconds*)
   454 (*SpyKeys*)
   446 (*SpyKeys*)
   455 by (blast_tac (claset() addDs [Says_imp_spies RS analz.Inj]) 3);
   447 by (blast_tac (claset() addDs [Says_imp_spies RS analz.Inj]) 3);
   456 (*Fake*) 
   448 (*Fake*) 
   457 by (spy_analz_tac 2);
   449 by (spy_analz_tac 2);
   458 (*Base*)
   450 (*Base*)
   459 by (Blast_tac 1);
   451 by (Blast_tac 1);
   460 qed "sessionK_not_spied";
   452 qed "sessionK_not_spied";
   461 Addsimps [sessionK_not_spied];
       
   462 
   453 
   463 
   454 
   464 (*If A sends ClientKeyExch to an honest B, then the PMS will stay secret.*)
   455 (*If A sends ClientKeyExch to an honest B, then the PMS will stay secret.*)
   465 Goal "[| evs : tls;  A ~: bad;  B ~: bad |]           \
   456 Goal "[| evs : tls;  A ~: bad;  B ~: bad |]           \
   466 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   457 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   470 by (REPEAT (fast_tac (claset() addss (simpset())) 6));
   461 by (REPEAT (fast_tac (claset() addss (simpset())) 6));
   471 (*ClientHello, ServerHello, ClientKeyExch, ServerResume: 
   462 (*ClientHello, ServerHello, ClientKeyExch, ServerResume: 
   472   mostly freshness reasoning*)
   463   mostly freshness reasoning*)
   473 by (REPEAT (blast_tac (claset() addSEs partsEs
   464 by (REPEAT (blast_tac (claset() addSEs partsEs
   474 				addDs  [Notes_Crypt_parts_spies,
   465 				addDs  [Notes_Crypt_parts_spies,
   475 					impOfSubs analz_subset_parts,
       
   476 					Says_imp_spies RS analz.Inj]) 3));
   466 					Says_imp_spies RS analz.Inj]) 3));
   477 (*SpyKeys*)
   467 (*SpyKeys*)
   478 by (fast_tac (claset() addss (simpset())) 2);
   468 by (fast_tac (claset() addss (simpset())) 2);
   479 (*Fake*)
   469 (*Fake*)
   480 by (spy_analz_tac 1);
   470 by (spy_analz_tac 1);
   499 (*Fake*)
   489 (*Fake*)
   500 by (spy_analz_tac 1);
   490 by (spy_analz_tac 1);
   501 (*ServerHello and ClientKeyExch: mostly freshness reasoning*)
   491 (*ServerHello and ClientKeyExch: mostly freshness reasoning*)
   502 by (REPEAT (blast_tac (claset() addSEs partsEs
   492 by (REPEAT (blast_tac (claset() addSEs partsEs
   503 				addDs  [Notes_Crypt_parts_spies,
   493 				addDs  [Notes_Crypt_parts_spies,
   504 					impOfSubs analz_subset_parts,
       
   505 					Says_imp_spies RS analz.Inj]) 1));
   494 					Says_imp_spies RS analz.Inj]) 1));
   506 bind_thm ("Spy_not_see_MS", result() RSN (2, rev_mp));
   495 bind_thm ("Spy_not_see_MS", result() RSN (2, rev_mp));
   507 
   496 
   508 
   497 
   509 (*** Weakening the Oops conditions for leakage of clientK ***)
   498 (*** Weakening the Oops conditions for leakage of clientK ***)
   510 
   499 
   511 (*If A created PMS then nobody other than the Spy would send a message
   500 (*If A created PMS then nobody else (except the Spy in replays) 
   512   using a clientK generated from that PMS.*)
   501   would send a message using a clientK generated from that PMS.*)
   513 Goal "[| evs : tls;  A' ~= Spy |]                \
   502 Goal "[| Says A' B' (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs;  \
   514 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs -->                  \
   503 \        Notes A {|Agent B, Nonce PMS|} : set evs;   \
   515 \         Says A' B' (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs -->  \
   504 \        evs : tls;  A' ~= Spy |]                \
   516 \         A = A'";
   505 \     ==> A = A'";
       
   506 by (etac rev_mp 1);
       
   507 by (etac rev_mp 1);
   517 by (analz_induct_tac 1);	(*8 seconds*)
   508 by (analz_induct_tac 1);	(*8 seconds*)
   518 by (ALLGOALS Clarify_tac);
   509 by (ALLGOALS Clarify_tac);
   519 (*ClientFinished, ClientResume: by unicity of PMS*)
   510 (*ClientFinished, ClientResume: by unicity of PMS*)
   520 by (REPEAT 
   511 by (REPEAT 
   521     (blast_tac (claset() addSDs [Notes_master_imp_Notes_PMS]
   512     (blast_tac (claset() addSDs [Notes_master_imp_Notes_PMS]
   522      	 	         addIs  [Notes_unique_PMS RS conjunct1]) 2));
   513      	 	         addIs  [Notes_unique_PMS RS conjunct1]) 2));
   523 (*ClientKeyExch*)
   514 (*ClientKeyExch*)
   524 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied,
   515 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied,
   525 				Says_imp_spies RS parts.Inj]) 1);
   516 				Says_imp_spies RS parts.Inj]) 1);
   526 bind_thm ("Says_clientK_unique",
   517 qed "Says_clientK_unique";
   527 	  result() RSN(2,rev_mp) RSN(2,rev_mp));
       
   528 
   518 
   529 
   519 
   530 (*If A created PMS and has not leaked her clientK to the Spy, 
   520 (*If A created PMS and has not leaked her clientK to the Spy, 
   531   then nobody has.*)
   521   then it is completely secure: not even in parts!*)
   532 Goal "evs : tls                         \
   522 Goal "[| Notes A {|Agent B, Nonce PMS|} : set evs;  \
   533 \     ==> Says A Spy (Key(clientK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs --> \
   523 \        Says A Spy (Key (clientK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs;  \
   534 \         Notes A {|Agent B, Nonce PMS|} : set evs -->                   \
   524 \        A ~: bad;  B ~: bad; \
   535 \         (ALL A. Says A Spy (Key(clientK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs)";
   525 \        evs : tls |]   \
   536 by (etac tls.induct 1);
   526 \     ==> Key (clientK(Na,Nb,PRF(PMS,NA,NB))) ~: parts (spies evs)";
   537 (*This roundabout proof sequence avoids looping in simplification*)
   527 by (etac rev_mp 1);
   538 by (ALLGOALS Simp_tac);
   528 by (etac rev_mp 1);
   539 by (ALLGOALS Clarify_tac);
   529 by (analz_induct_tac 1);        (*17 seconds*)
   540 by (Fake_parts_insert_tac 1);
       
   541 by (ALLGOALS Asm_simp_tac);
       
   542 (*Oops*)
   530 (*Oops*)
   543 by (blast_tac (claset() addIs [Says_clientK_unique]) 2);
   531 by (blast_tac (claset() addIs [Says_clientK_unique]) 4);
   544 (*ClientKeyExch*)
   532 (*ClientKeyExch*)
   545 by (blast_tac (claset() addSDs [PMS_sessionK_not_spied]
   533 by (blast_tac (claset() addSDs [PMS_sessionK_not_spied]) 3);
   546 			addSEs spies_partsEs) 1);
   534 (*SpyKeys*)
   547 qed_spec_mp "clientK_Oops_ALL";
   535 by (blast_tac (claset() addSEs [Spy_not_see_MS RSN (2,rev_notE)]) 2);
   548 
   536 (*Fake*) 
       
   537 by (spy_analz_tac 1);
       
   538 qed "clientK_not_spied";
   549 
   539 
   550 
   540 
   551 (*** Weakening the Oops conditions for leakage of serverK ***)
   541 (*** Weakening the Oops conditions for leakage of serverK ***)
   552 
   542 
   553 (*If A created PMS for B, then nobody other than B or the Spy would
   543 (*If A created PMS for B, then nobody other than B or the Spy would
   554   send a message using a serverK generated from that PMS.*)
   544   send a message using a serverK generated from that PMS.*)
   555 Goal "[| evs : tls;  A ~: bad;  B ~: bad;  B' ~= Spy |]                \
   545 Goal "[| Says B' A' (Crypt (serverK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs;  \
   556 \     ==> Notes A {|Agent B, Nonce PMS|} : set evs -->                  \
   546 \        Notes A {|Agent B, Nonce PMS|} : set evs;  \
   557 \         Says B' A' (Crypt (serverK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs -->  \
   547 \        evs : tls;  A ~: bad;  B ~: bad;  B' ~= Spy |]                \
   558 \         B = B'";
   548 \     ==> B = B'";
       
   549 by (etac rev_mp 1);
       
   550 by (etac rev_mp 1);
   559 by (analz_induct_tac 1);	(*9 seconds*)
   551 by (analz_induct_tac 1);	(*9 seconds*)
   560 by (ALLGOALS Clarify_tac);
   552 by (ALLGOALS Clarify_tac);
   561 (*ServerResume, ServerFinished: by unicity of PMS*)
   553 (*ServerResume, ServerFinished: by unicity of PMS*)
   562 by (REPEAT
   554 by (REPEAT
   563     (blast_tac (claset() addSEs [MPair_parts]
   555     (blast_tac (claset() addSDs [Notes_master_imp_Crypt_PMS]
   564 			 addSDs [Notes_master_imp_Crypt_PMS, 
       
   565 				 Says_imp_spies RS parts.Inj]
       
   566 			 addDs  [Spy_not_see_PMS, 
   556 			 addDs  [Spy_not_see_PMS, 
   567 				 Notes_Crypt_parts_spies,
   557 				 Notes_Crypt_parts_spies,
   568 				 Crypt_unique_PMS]) 2));
   558 				 Crypt_unique_PMS]) 2));
   569 (*ClientKeyExch*)
   559 (*ClientKeyExch*)
   570 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied,
   560 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied,
   571 				Says_imp_spies RS parts.Inj]) 1);
   561 				Says_imp_spies RS parts.Inj]) 1);
   572 bind_thm ("Says_serverK_unique",
   562 qed "Says_serverK_unique";
   573 	  result() RSN(2,rev_mp) RSN(2,rev_mp));
       
   574 
   563 
   575 (*If A created PMS for B, and B has not leaked his serverK to the Spy, 
   564 (*If A created PMS for B, and B has not leaked his serverK to the Spy, 
   576   then nobody has.*)
   565   then it is completely secure: not even in parts!*)
   577 Goal "[| evs : tls;  A ~: bad;  B ~: bad |]                        \
   566 Goal "[| Notes A {|Agent B, Nonce PMS|} : set evs;  \
   578 \  ==> Says B Spy (Key(serverK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs --> \
   567 \        Says B Spy (Key(serverK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs; \
   579 \   Notes A {|Agent B, Nonce PMS|} : set evs -->                   \
   568 \        evs : tls;  A ~: bad;  B ~: bad |]                        \
   580 \   (ALL A. Says A Spy (Key(serverK(Na,Nb,PRF(PMS,NA,NB)))) ~: set evs) ";
   569 \     ==> Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: parts (spies evs)";
   581 by (etac tls.induct 1);
   570 by (etac rev_mp 1);
   582 (*This roundabout proof sequence avoids looping in simplification*)
   571 by (etac rev_mp 1);
   583 by (ALLGOALS Simp_tac);
   572 by (analz_induct_tac 1);        (*6 seconds*)
   584 by (ALLGOALS Clarify_tac);
       
   585 by (Fake_parts_insert_tac 1);
       
   586 by (ALLGOALS Asm_simp_tac);
       
   587 (*Oops*)
   573 (*Oops*)
   588 by (blast_tac (claset() addIs [Says_serverK_unique]) 2);
   574 by (blast_tac (claset() addIs [Says_serverK_unique]) 4);
   589 (*ClientKeyExch*)
   575 (*ClientKeyExch*)
   590 by (blast_tac (claset() addSDs [PMS_sessionK_not_spied]
   576 by (blast_tac (claset() addSDs [PMS_sessionK_not_spied]) 3);
   591 			addSEs spies_partsEs) 1);
   577 (*SpyKeys*)
   592 qed_spec_mp "serverK_Oops_ALL";
   578 by (blast_tac (claset() addSEs [Spy_not_see_MS RSN (2,rev_notE)]) 2);
   593 
   579 (*Fake*) 
       
   580 by (spy_analz_tac 1);
       
   581 qed "serverK_not_spied";
   594 
   582 
   595 
   583 
   596 (*** Protocol goals: if A receives ServerFinished, then B is present 
   584 (*** Protocol goals: if A receives ServerFinished, then B is present 
   597      and has used the quoted values PA, PB, etc.  Note that it is up to A
   585      and has used the quoted values PA, PB, etc.  Note that it is up to A
   598      to compare PA with what she originally sent.
   586      to compare PA with what she originally sent.
   603 \              (Hash{|Number SID, Nonce M,             \
   591 \              (Hash{|Number SID, Nonce M,             \
   604 \                     Nonce Na, Number PA, Agent A,    \
   592 \                     Nonce Na, Number PA, Agent A,    \
   605 \                     Nonce Nb, Number PB, Agent B|}); \
   593 \                     Nonce Nb, Number PB, Agent B|}); \
   606 \        M = PRF(PMS,NA,NB);                           \
   594 \        M = PRF(PMS,NA,NB);                           \
   607 \        evs : tls;  A ~: bad;  B ~: bad |]            \
   595 \        evs : tls;  A ~: bad;  B ~: bad |]            \
   608 \     ==> (ALL A. Says A Spy (Key(serverK(Na,Nb,M))) ~: set evs) --> \
   596 \     ==> Says B Spy (Key(serverK(Na,Nb,M))) ~: set evs --> \
   609 \         Notes A {|Agent B, Nonce PMS|} : set evs --> \
   597 \         Notes A {|Agent B, Nonce PMS|} : set evs --> \
   610 \         X : parts (spies evs) --> Says B A X : set evs";
   598 \         X : parts (spies evs) --> Says B A X : set evs";
   611 by (hyp_subst_tac 1);
   599 by (hyp_subst_tac 1);
   612 by (analz_induct_tac 1);        (*10 seconds*)
   600 by (analz_induct_tac 1);        (*10 seconds*)
   613 by (ALLGOALS (asm_simp_tac (simpset() addsimps [all_conj_distrib])));
   601 by (ALLGOALS (asm_simp_tac (simpset() addsimps [all_conj_distrib])));
   614 by (ALLGOALS Clarify_tac);
   602 by (ALLGOALS Clarify_tac);
   615 (*ClientKeyExch*)
   603 (*ClientKeyExch*)
   616 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   604 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   617 (*Fake: the Spy doesn't have the critical session key!*)
   605 (*Fake: the Spy doesn't have the critical session key!*)
   618 by (subgoal_tac "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(spies evs)" 1);
   606 by (blast_tac (claset() addEs [serverK_not_spied RSN (2,rev_notE)]) 1);
   619 by (asm_simp_tac (simpset() addsimps [Spy_not_see_MS, 
       
   620 				      not_parts_not_analz]) 2);
       
   621 by (Fake_parts_insert_tac 1);
       
   622 val lemma = normalize_thm [RSmp] (result());
       
   623 
       
   624 (*Final version*)
       
   625 Goal "[| X = Crypt (serverK(Na,Nb,M))                  \
       
   626 \              (Hash{|Number SID, Nonce M,             \
       
   627 \                     Nonce Na, Number PA, Agent A,    \
       
   628 \                     Nonce Nb, Number PB, Agent B|}); \
       
   629 \        M = PRF(PMS,NA,NB);                           \
       
   630 \        X : parts (spies evs);                        \
       
   631 \        Notes A {|Agent B, Nonce PMS|} : set evs;     \
       
   632 \        Says B Spy (Key (serverK(Na,Nb,M))) ~: set evs; \
       
   633 \        evs : tls;  A ~: bad;  B ~: bad |]          \
       
   634 \     ==> Says B A X : set evs";
       
   635 by (blast_tac (claset() addIs [lemma]
       
   636                         addEs [serverK_Oops_ALL RSN(2, rev_notE)]) 1);
       
   637 qed_spec_mp "TrustServerFinished";
   607 qed_spec_mp "TrustServerFinished";
   638 
       
   639 
   608 
   640 
   609 
   641 (*This version refers not to ServerFinished but to any message from B.
   610 (*This version refers not to ServerFinished but to any message from B.
   642   We don't assume B has received CertVerify, and an intruder could
   611   We don't assume B has received CertVerify, and an intruder could
   643   have changed A's identity in all other messages, so we can't be sure
   612   have changed A's identity in all other messages, so we can't be sure
   644   that B sends his message to A.  If CLIENT KEY EXCHANGE were augmented
   613   that B sends his message to A.  If CLIENT KEY EXCHANGE were augmented
   645   to bind A's identity with PMS, then we could replace A' by A below.*)
   614   to bind A's identity with PMS, then we could replace A' by A below.*)
   646 Goal "[| M = PRF(PMS,NA,NB);  evs : tls;  A ~: bad;  B ~: bad |]     \
   615 Goal "[| M = PRF(PMS,NA,NB);  evs : tls;  A ~: bad;  B ~: bad |]     \
   647 \     ==> (ALL A. Says A Spy (Key(serverK(Na,Nb,M))) ~: set evs) --> \
   616 \     ==> Says B Spy (Key(serverK(Na,Nb,M))) ~: set evs --> \
   648 \         Notes A {|Agent B, Nonce PMS|} : set evs -->              \
   617 \         Notes A {|Agent B, Nonce PMS|} : set evs -->              \
   649 \         Crypt (serverK(Na,Nb,M)) Y : parts (spies evs)  -->  \
   618 \         Crypt (serverK(Na,Nb,M)) Y : parts (spies evs)  -->  \
   650 \         (EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs)";
   619 \         (EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs)";
   651 by (hyp_subst_tac 1);
   620 by (hyp_subst_tac 1);
   652 by (analz_induct_tac 1);	(*20 seconds*)
   621 by (analz_induct_tac 1);	(*20 seconds*)
   653 by (ALLGOALS (asm_simp_tac (simpset() addsimps [ex_disj_distrib])));
   622 by (ALLGOALS (asm_simp_tac (simpset() addsimps [ex_disj_distrib])));
   654 by (ALLGOALS Clarify_tac);
   623 by (ALLGOALS Clarify_tac);
   655 (*ServerResume, ServerFinished: by unicity of PMS*)
   624 (*ServerResume, ServerFinished: by unicity of PMS*)
   656 by (REPEAT
   625 by (REPEAT
   657     (blast_tac (claset() addSEs [MPair_parts]
   626     (blast_tac (claset() addSDs [Notes_master_imp_Crypt_PMS]
   658 			 addSDs [Notes_master_imp_Crypt_PMS, 
       
   659 				 Says_imp_spies RS parts.Inj]
       
   660 			 addDs  [Spy_not_see_PMS, 
   627 			 addDs  [Spy_not_see_PMS, 
   661 				 Notes_Crypt_parts_spies,
   628 				 Notes_Crypt_parts_spies,
   662 				 Crypt_unique_PMS]) 3));
   629 				 Crypt_unique_PMS]) 3));
   663 (*ClientKeyExch*)
   630 (*ClientKeyExch*)
   664 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   631 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   665 (*Fake: the Spy doesn't have the critical session key!*)
   632 (*Fake: the Spy doesn't have the critical session key!*)
   666 by (subgoal_tac "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(spies evs)" 1);
   633 by (blast_tac (claset() addEs [serverK_not_spied RSN (2,rev_notE)]) 1);
   667 by (asm_simp_tac (simpset() addsimps [Spy_not_see_MS, 
       
   668 				      not_parts_not_analz]) 2);
       
   669 by (Fake_parts_insert_tac 1);
       
   670 val lemma = normalize_thm [RSmp] (result());
       
   671 
       
   672 (*Final version*)
       
   673 Goal "[| M = PRF(PMS,NA,NB);                           \
       
   674 \        Crypt (serverK(Na,Nb,M)) Y : parts (spies evs); \
       
   675 \        Notes A {|Agent B, Nonce PMS|} : set evs;     \
       
   676 \        Says B Spy (Key (serverK(Na,Nb,M))) ~: set evs; \
       
   677 \        evs : tls;  A ~: bad;  B ~: bad |]          \
       
   678 \     ==> EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs";
       
   679 by (blast_tac (claset() addIs [lemma]
       
   680                         addEs [serverK_Oops_ALL RSN(2, rev_notE)]) 1);
       
   681 qed_spec_mp "TrustServerMsg";
   634 qed_spec_mp "TrustServerMsg";
   682 
       
   683 
   635 
   684 
   636 
   685 (*** Protocol goal: if B receives any message encrypted with clientK
   637 (*** Protocol goal: if B receives any message encrypted with clientK
   686      then A has sent it, ASSUMING that A chose PMS.  Authentication is
   638      then A has sent it, ASSUMING that A chose PMS.  Authentication is
   687      assumed here; B cannot verify it.  But if the message is
   639      assumed here; B cannot verify it.  But if the message is
   688      ClientFinished, then B can then check the quoted values PA, PB, etc.
   640      ClientFinished, then B can then check the quoted values PA, PB, etc.
   689 ***)
   641 ***)
   690 
   642 
   691 Goal "[| M = PRF(PMS,NA,NB);  evs : tls;  A ~: bad;  B ~: bad |] \
   643 Goal "[| M = PRF(PMS,NA,NB);  evs : tls;  A ~: bad;  B ~: bad |] \
   692 \     ==> (ALL A. Says A Spy (Key(clientK(Na,Nb,M))) ~: set evs) --> \
   644 \     ==> Says A Spy (Key(clientK(Na,Nb,M))) ~: set evs --> \
   693 \         Notes A {|Agent B, Nonce PMS|} : set evs -->               \
   645 \         Notes A {|Agent B, Nonce PMS|} : set evs -->               \
   694 \         Crypt (clientK(Na,Nb,M)) Y : parts (spies evs) -->         \
   646 \         Crypt (clientK(Na,Nb,M)) Y : parts (spies evs) -->         \
   695 \         Says A B (Crypt (clientK(Na,Nb,M)) Y) : set evs";
   647 \         Says A B (Crypt (clientK(Na,Nb,M)) Y) : set evs";
   696 by (hyp_subst_tac 1);
   648 by (hyp_subst_tac 1);
   697 by (analz_induct_tac 1);	(*15 seconds*)
   649 by (analz_induct_tac 1);	(*15 seconds*)
   701 		                addSDs [Notes_master_imp_Notes_PMS]
   653 		                addSDs [Notes_master_imp_Notes_PMS]
   702 	 	                addDs  [Notes_unique_PMS]) 3));
   654 	 	                addDs  [Notes_unique_PMS]) 3));
   703 (*ClientKeyExch*)
   655 (*ClientKeyExch*)
   704 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   656 by (blast_tac (claset() addSDs [PMS_Crypt_sessionK_not_spied]) 2);
   705 (*Fake: the Spy doesn't have the critical session key!*)
   657 (*Fake: the Spy doesn't have the critical session key!*)
   706 by (subgoal_tac "Key (clientK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(spies evs)" 1);
   658 by (blast_tac (claset() addEs [clientK_not_spied RSN (2,rev_notE)]) 1);
   707 by (asm_simp_tac (simpset() addsimps [Spy_not_see_MS, 
   659 qed_spec_mp "TrustClientMsg";
   708 				      not_parts_not_analz]) 2);
       
   709 by (Fake_parts_insert_tac 1);
       
   710 val lemma = normalize_thm [RSmp] (result());
       
   711 
       
   712 (*Final version*)
       
   713 Goal "[| M = PRF(PMS,NA,NB);                           \
       
   714 \        Crypt (clientK(Na,Nb,M)) Y : parts (spies evs);  \
       
   715 \        Notes A {|Agent B, Nonce PMS|} : set evs;        \
       
   716 \        Says A Spy (Key(clientK(Na,Nb,M))) ~: set evs;  \
       
   717 \        evs : tls;  A ~: bad;  B ~: bad |]                         \
       
   718 \     ==> Says A B (Crypt (clientK(Na,Nb,M)) Y) : set evs";
       
   719 by (blast_tac (claset() addIs [lemma]
       
   720                         addEs [clientK_Oops_ALL RSN(2, rev_notE)]) 1);
       
   721 qed "TrustClientMsg";
       
   722 
   660 
   723 
   661 
   724 
   662 
   725 (*** Protocol goal: if B receives ClientFinished, and if B is able to
   663 (*** Protocol goal: if B receives ClientFinished, and if B is able to
   726      check a CertVerify from A, then A has used the quoted
   664      check a CertVerify from A, then A has used the quoted
   741 (*22/9/97: loads in 622s, which is 10 minutes 22 seconds*)
   679 (*22/9/97: loads in 622s, which is 10 minutes 22 seconds*)
   742 (*24/9/97: loads in 672s, which is 11 minutes 12 seconds [stronger theorems]*)
   680 (*24/9/97: loads in 672s, which is 11 minutes 12 seconds [stronger theorems]*)
   743 (*29/9/97: loads in 481s, after removing Certificate from ClientKeyExch*)
   681 (*29/9/97: loads in 481s, after removing Certificate from ClientKeyExch*)
   744 (*30/9/97: loads in 476s, after removing unused theorems*)
   682 (*30/9/97: loads in 476s, after removing unused theorems*)
   745 (*30/9/97: loads in 448s, after fixing ServerResume*)
   683 (*30/9/97: loads in 448s, after fixing ServerResume*)
       
   684 
       
   685 (*08/9/97: loads in 189s (pike), after much reorganization, 
       
   686            back to 621s on albatross?*)