src/HOL/Auth/TLS.ML
changeset 3515 d8a71f6eaf40
parent 3506 a36e0a49d2cd
child 3519 ab0a9fbed4c0
equal deleted inserted replaced
3514:eb16b8e8d872 3515:d8a71f6eaf40
     1 (*  Title:      HOL/Auth/TLS
     1 (*  Title:      HOL/Auth/TLS
     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   1997  University of Cambridge
     4     Copyright   1997  University of Cambridge
     5 
       
     6 The public-key model has a weakness, especially concerning anonymous sessions.
       
     7 The Spy's state is recorded as the trace of message.  But if he himself is the
       
     8 Client and invents M, then he encrypts M with B's public key before sending
       
     9 it.  This message gives no evidence that the spy knows M, and yet the spy
       
    10 actually chose M!  So, in any property concerning the secrecy of some item,
       
    11 one must establish that the spy didn't choose the item.  Guarantees normally
       
    12 assume that the other party is uncompromised (otherwise, one can prove
       
    13 little).
       
    14 
     5 
    15 Protocol goals: 
     6 Protocol goals: 
    16 * M, serverK(NA,NB,M) and clientK(NA,NB,M) will be known only to the two
     7 * M, serverK(NA,NB,M) and clientK(NA,NB,M) will be known only to the two
    17      parties (though A is not necessarily authenticated).
     8      parties (though A is not necessarily authenticated).
    18 
     9 
    82 goal thy "clientK arg ~= serverK arg'";
    73 goal thy "clientK arg ~= serverK arg'";
    83 by (cut_facts_tac [rangeI RS impOfSubs clientK_range] 1);
    74 by (cut_facts_tac [rangeI RS impOfSubs clientK_range] 1);
    84 by (Blast_tac 1);
    75 by (Blast_tac 1);
    85 qed "clientK_neq_serverK";
    76 qed "clientK_neq_serverK";
    86 
    77 
    87 val ths = [pubK_neq_clientK, pubK_neq_serverK, 
    78 val keys_distinct = [pubK_neq_clientK, pubK_neq_serverK, 
    88 	   priK_neq_clientK, priK_neq_serverK, clientK_neq_serverK];
    79 		     priK_neq_clientK, priK_neq_serverK, clientK_neq_serverK];
    89 AddIffs (ths @ (ths RL [not_sym]));
    80 AddIffs (keys_distinct @ (keys_distinct RL [not_sym]));
    90 
    81 
    91 
    82 
    92 (**** Protocol Proofs ****)
    83 (**** Protocol Proofs ****)
    93 
    84 
    94 (*A "possibility property": there are traces that reach the end.
    85 (*A "possibility property": there are traces that reach the end.
   153 goal thy 
   144 goal thy 
   154  "!!evs. evs : tls \
   145  "!!evs. evs : tls \
   155 \        ==> (Key (priK A) : parts (sees lost Spy evs)) = (A : lost)";
   146 \        ==> (Key (priK A) : parts (sees lost Spy evs)) = (A : lost)";
   156 by (etac tls.induct 1);
   147 by (etac tls.induct 1);
   157 by (prove_simple_subgoals_tac 1);
   148 by (prove_simple_subgoals_tac 1);
       
   149 by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 2);
   158 by (Fake_parts_insert_tac 1);
   150 by (Fake_parts_insert_tac 1);
   159 qed "Spy_see_priK";
   151 qed "Spy_see_priK";
   160 Addsimps [Spy_see_priK];
   152 Addsimps [Spy_see_priK];
   161 
   153 
   162 goal thy 
   154 goal thy 
   173 
   165 
   174 bind_thm ("Spy_analz_priK_D", analz_subset_parts RS subsetD RS Spy_see_priK_D);
   166 bind_thm ("Spy_analz_priK_D", analz_subset_parts RS subsetD RS Spy_see_priK_D);
   175 AddSDs [Spy_see_priK_D, Spy_analz_priK_D];
   167 AddSDs [Spy_see_priK_D, Spy_analz_priK_D];
   176 
   168 
   177 
   169 
       
   170 (*This lemma says that no false certificates exist.  One might extend the
       
   171   model to include bogus certificates for the lost agents, but there seems
       
   172   little point in doing so: the loss of their private keys is a worse
       
   173   breach of security.*)
       
   174 goalw thy [certificate_def]
       
   175  "!!evs. evs : tls     \
       
   176 \        ==> certificate B KB : parts (sees lost Spy evs) --> KB = pubK B";
       
   177 by (etac tls.induct 1);
       
   178 by (ALLGOALS (asm_full_simp_tac (!simpset setloop split_tac [expand_if])));
       
   179 by (Fake_parts_insert_tac 2);
       
   180 by (Blast_tac 1);
       
   181 bind_thm ("Server_cert_pubB", result() RSN (2, rev_mp));
       
   182 
       
   183 
       
   184 (*Replace key KB in ClientCertKeyEx by (pubK B) *)
       
   185 val ClientCertKeyEx_tac = 
       
   186     forward_tac [Says_imp_sees_Spy' RS parts.Inj RS 
       
   187 		 parts.Snd RS parts.Snd RS parts.Snd RS Server_cert_pubB]
       
   188     THEN' assume_tac
       
   189     THEN' hyp_subst_tac;
       
   190 
       
   191 fun analz_induct_tac i = 
       
   192     etac tls.induct i   THEN
       
   193     ClientCertKeyEx_tac  (i+7)  THEN	(*ClientFinished*)
       
   194     ClientCertKeyEx_tac  (i+6)  THEN	(*CertVerify*)
       
   195     ClientCertKeyEx_tac  (i+5)  THEN	(*ClientCertKeyEx*)
       
   196     rewrite_goals_tac  [certificate_def]  THEN
       
   197     ALLGOALS (asm_simp_tac 
       
   198               (!simpset addsimps [not_parts_not_analz]
       
   199                         setloop split_tac [expand_if]))  THEN
       
   200     (*Remove instances of pubK B:  the Spy already knows all public keys.
       
   201       Combining the two simplifier calls makes them run extremely slowly.*)
       
   202     ALLGOALS (asm_simp_tac 
       
   203               (!simpset addsimps [insert_absorb]
       
   204                         setloop split_tac [expand_if]));
       
   205 
       
   206 
       
   207 (*** Hashing of nonces ***)
       
   208 
   178 (*Every Nonce that's hashed is already in past traffic. *)
   209 (*Every Nonce that's hashed is already in past traffic. *)
   179 goal thy "!!evs. [| Hash {|Nonce N, X|} : parts (sees lost Spy evs);  \
   210 goal thy "!!evs. [| Hash {|Nonce N, X|} : parts (sees lost Spy evs);  \
   180 \                   evs : tls |]  \
   211 \                   evs : tls |]  \
   181 \                ==> Nonce N : parts (sees lost Spy evs)";
   212 \                ==> Nonce N : parts (sees lost Spy evs)";
   182 by (etac rev_mp 1);
   213 by (etac rev_mp 1);
   183 by (etac tls.induct 1);
   214 by (etac tls.induct 1);
   184 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees])));
   215 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]
   185 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
   216 			             setloop split_tac [expand_if])));
   186 		      addSEs partsEs) 1);
   217 by (Fake_parts_insert_tac 2);
   187 by (Fake_parts_insert_tac 1);
   218 by (REPEAT (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
       
   219 		               addSEs partsEs) 1));
   188 qed "Hash_imp_Nonce1";
   220 qed "Hash_imp_Nonce1";
   189 
   221 
   190 (*Lemma needed to prove Hash_Hash_imp_Nonce*)
   222 (*Lemma needed to prove Hash_Hash_imp_Nonce*)
   191 goal thy "!!evs. [| Hash{|Nonce NA, Nonce NB, Nonce M|}  \
   223 goal thy "!!evs. [| Hash{|Nonce NA, Nonce NB, Nonce M|}  \
   192 \                       : parts (sees lost Spy evs);     \
   224 \                       : parts (sees lost Spy evs);     \
   193 \                   evs : tls |]  \
   225 \                   evs : tls |]  \
   194 \                ==> Nonce M : parts (sees lost Spy evs)";
   226 \                ==> Nonce M : parts (sees lost Spy evs)";
   195 by (etac rev_mp 1);
   227 by (etac rev_mp 1);
   196 by (etac tls.induct 1);
   228 by (etac tls.induct 1);
   197 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees])));
   229 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]
   198 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
   230 			             setloop split_tac [expand_if])));
   199 		      addSEs partsEs) 1);
   231 by (Fake_parts_insert_tac 2);
   200 by (Fake_parts_insert_tac 1);
   232 by (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
       
   233 		       addSEs partsEs) 1);
   201 qed "Hash_imp_Nonce2";
   234 qed "Hash_imp_Nonce2";
   202 AddSDs [Hash_imp_Nonce2];
   235 AddSDs [Hash_imp_Nonce2];
   203 
   236 
       
   237 
       
   238 goal thy "!!evs. [| Notes A {|Agent B, X|} : set evs;  evs : tls |]  \
       
   239 \                ==> Crypt (pubK B) X : parts (sees lost Spy evs)";
       
   240 by (etac rev_mp 1);
       
   241 by (analz_induct_tac 1);
       
   242 by (blast_tac (!claset addIs [parts_insertI]) 1);
       
   243 qed "Notes_Crypt_parts_sees";
       
   244 
       
   245 
       
   246 (*NEEDED??*)
   204 goal thy "!!evs. [| Hash {| Hash{|Nonce NA, Nonce NB, Nonce M|}, X |}  \
   247 goal thy "!!evs. [| Hash {| Hash{|Nonce NA, Nonce NB, Nonce M|}, X |}  \
   205 \                      : parts (sees lost Spy evs);      \
   248 \                      : parts (sees lost Spy evs);      \
   206 \                   evs : tls |]                         \
   249 \                   evs : tls |]                         \
   207 \                ==> Nonce M : parts (sees lost Spy evs)";
   250 \                ==> Nonce M : parts (sees lost Spy evs)";
   208 by (etac rev_mp 1);
   251 by (etac rev_mp 1);
   209 by (etac tls.induct 1);
   252 by (etac tls.induct 1);
   210 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees])));
   253 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]
   211 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
   254 			             setloop split_tac [expand_if])));
       
   255 by (Fake_parts_insert_tac 2);
       
   256 by (step_tac (!claset addSDs [Notes_Crypt_parts_sees,
       
   257 			      Says_imp_sees_Spy' RS parts.Inj]
   212 		      addSEs partsEs) 1);
   258 		      addSEs partsEs) 1);
   213 by (Fake_parts_insert_tac 1);
       
   214 qed "Hash_Hash_imp_Nonce";
   259 qed "Hash_Hash_imp_Nonce";
   215 
   260 
   216 
   261 
   217 (*NEEDED??
   262 (*NEEDED??
   218   Every Nonce that's hashed is already in past traffic. 
   263   Every Nonce that's hashed is already in past traffic. 
   221 goal thy "!!evs. [| Hash X : parts (sees lost Spy evs);  \
   266 goal thy "!!evs. [| Hash X : parts (sees lost Spy evs);  \
   222 \                   Nonce N : parts {X};  evs : tls |]  \
   267 \                   Nonce N : parts {X};  evs : tls |]  \
   223 \                ==> Nonce N : parts (sees lost Spy evs)";
   268 \                ==> Nonce N : parts (sees lost Spy evs)";
   224 by (etac rev_mp 1);
   269 by (etac rev_mp 1);
   225 by (etac tls.induct 1);
   270 by (etac tls.induct 1);
   226 by (ALLGOALS Asm_simp_tac);
   271 by (ALLGOALS (asm_simp_tac (!simpset setloop split_tac [expand_if])));
   227 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj]
   272 by (step_tac (!claset addSDs [Notes_Crypt_parts_sees,
       
   273 			      Says_imp_sees_Spy' RS parts.Inj]
   228 		      addSEs partsEs) 1);
   274 		      addSEs partsEs) 1);
   229 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [parts_insert_sees])));
   275 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [parts_insert_sees])));
   230 by (Fake_parts_insert_tac 1);
   276 by (Fake_parts_insert_tac 1);
   231 (*CertVerify, ClientFinished, ServerFinished (?)*)
   277 (*CertVerify, ClientFinished, ServerFinished (?)*)
   232 by (REPEAT (Blast_tac 1));
   278 by (REPEAT (Blast_tac 1));
   246 \    ==> Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|}  \
   292 \    ==> Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|}  \
   247 \          : set evs --> \
   293 \          : set evs --> \
   248 \        X : parts (sees lost Spy evs) --> Says A B X : set evs";
   294 \        X : parts (sees lost Spy evs) --> Says A B X : set evs";
   249 by (hyp_subst_tac 1);
   295 by (hyp_subst_tac 1);
   250 by (etac tls.induct 1);
   296 by (etac tls.induct 1);
   251 by (ALLGOALS Asm_simp_tac);
   297 by (ALLGOALS (asm_simp_tac (!simpset setloop split_tac [expand_if])));
   252 by (Fake_parts_insert_tac 1);
   298 by (Fake_parts_insert_tac 1);
   253 (*ServerHello: nonce NB cannot be in X because it's fresh!*)
   299 (*ServerHello: nonce NB cannot be in X because it's fresh!*)
   254 by (blast_tac (!claset addSDs [Hash_imp_Nonce1]
   300 by (blast_tac (!claset addSDs [Hash_imp_Nonce1]
   255 	               addSEs sees_Spy_partsEs) 1);
   301 	               addSEs sees_Spy_partsEs) 1);
   256 qed_spec_mp "TrustCertVerify";
   302 qed_spec_mp "TrustCertVerify";
   257 
   303 
   258 
   304 
       
   305 (*If CERTIFICATE VERIFY is present then A has chosen M.*)
   259 goal thy
   306 goal thy
   260  "!!evs. [| evs : tls;  A ~= Spy |]                                      \
   307  "!!evs. [| Crypt (priK A) (Hash{|Nonce NB, certificate B KB, Nonce M|})  \
   261 \ ==> Says A B (Crypt (priK A)                                           \
   308 \             : parts (sees lost Spy evs);                                \
   262 \               (Hash{|Nonce NB, certificate B KB, Nonce M|})) : set evs \
   309 \           evs : tls;  A ~: lost |]                                      \
   263 \     --> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} : set evs";
   310 \        ==> Notes A {|Agent B, Nonce M|} : set evs";
   264 by (etac tls.induct 1);
   311 be rev_mp 1;
   265 by (ALLGOALS Asm_full_simp_tac);
   312 by (etac tls.induct 1);
   266 bind_thm ("UseCertVerify", result() RSN (2, rev_mp));
   313 by (ALLGOALS (asm_full_simp_tac (!simpset setloop split_tac [expand_if])));
   267 
       
   268 
       
   269 (*This lemma says that no false certificates exist.  One might extend the
       
   270   model to include bogus certificates for the lost agents, but there seems
       
   271   little point in doing so: the loss of their private keys is a worse
       
   272   breach of security.*)
       
   273 goalw thy [certificate_def]
       
   274  "!!evs. evs : tls     \
       
   275 \        ==> certificate B KB : parts (sees lost Spy evs) --> KB = pubK B";
       
   276 by (etac tls.induct 1);
       
   277 by (ALLGOALS Asm_simp_tac);
       
   278 by (Fake_parts_insert_tac 2);
   314 by (Fake_parts_insert_tac 2);
   279 by (Blast_tac 1);
   315 by (Blast_tac 1);
   280 bind_thm ("Server_cert_pubB", result() RSN (2, rev_mp));
   316 qed "UseCertVerify";
   281 
   317 
   282 
       
   283 (*Replace key KB in ClientCertKeyEx by (pubK B) *)
       
   284 val ClientCertKeyEx_tac = 
       
   285     forward_tac [Says_imp_sees_Spy' RS parts.Inj RS 
       
   286 		 parts.Snd RS parts.Snd RS parts.Snd RS Server_cert_pubB]
       
   287     THEN' assume_tac
       
   288     THEN' hyp_subst_tac;
       
   289 
       
   290 fun analz_induct_tac i = 
       
   291     etac tls.induct i   THEN
       
   292     ClientCertKeyEx_tac  (i+5)  THEN
       
   293     ALLGOALS (asm_simp_tac 
       
   294               (!simpset addsimps [not_parts_not_analz]
       
   295                         setloop split_tac [expand_if]))  THEN
       
   296     (*Remove instances of pubK B:  the Spy already knows all public keys.
       
   297       Combining the two simplifier calls makes them run extremely slowly.*)
       
   298     ALLGOALS (asm_simp_tac 
       
   299               (!simpset addsimps [insert_absorb]
       
   300                         setloop split_tac [expand_if]));
       
   301 
       
   302 (*** Specialized rewriting for the analz_image_... theorems ***)
       
   303 
       
   304 goal thy "insert (Key K) H = Key `` {K} Un H";
       
   305 by (Blast_tac 1);
       
   306 qed "insert_Key_singleton";
       
   307 
       
   308 goal thy "insert (Key K) (Key``KK Un C) = Key `` (insert K KK) Un C";
       
   309 by (Blast_tac 1);
       
   310 qed "insert_Key_image";
       
   311 
       
   312 (*Reverse the normal simplification of "image" to build up (not break down)
       
   313   the set of keys.  Based on analz_image_freshK_ss, but simpler.*)
       
   314 val analz_image_keys_ss = 
       
   315      !simpset delsimps [image_insert, image_Un]
       
   316               addsimps [image_insert RS sym, image_Un RS sym,
       
   317 			rangeI, 
       
   318 			insert_Key_singleton, 
       
   319 			insert_Key_image, Un_assoc RS sym]
       
   320               setloop split_tac [expand_if];
       
   321 
   318 
   322 (*No collection of keys can help the spy get new private keys*)
   319 (*No collection of keys can help the spy get new private keys*)
   323 goal thy  
   320 goal thy  
   324  "!!evs. evs : tls ==>                                    \
   321  "!!evs. evs : tls ==>                                    \
   325 \  ALL KK. (Key(priK B) : analz (Key``KK Un (sees lost Spy evs))) =  \
   322 \  ALL KK. (Key(priK B) : analz (Key``KK Un (sees lost Spy evs))) =  \
   326 \            (priK B : KK | B : lost)";
   323 \            (priK B : KK | B : lost)";
   327 by (etac tls.induct 1);
   324 by (etac tls.induct 1);
   328 by (ALLGOALS (asm_simp_tac analz_image_keys_ss));
   325 by (ALLGOALS
       
   326     (asm_simp_tac (analz_image_keys_ss 
       
   327 		   addsimps (certificate_def::keys_distinct))));
   329 (*Fake*) 
   328 (*Fake*) 
   330 by (spy_analz_tac 2);
   329 by (spy_analz_tac 2);
   331 (*Base*)
   330 (*Base*)
   332 by (Blast_tac 1);
   331 by (Blast_tac 1);
   333 qed_spec_mp "analz_image_priK";
   332 qed_spec_mp "analz_image_priK";
   347 \            (Nonce N : analz (Key``KK Un (sees lost Spy evs))) = \
   346 \            (Nonce N : analz (Key``KK Un (sees lost Spy evs))) = \
   348 \            (Nonce N : analz (sees lost Spy evs))";
   347 \            (Nonce N : analz (sees lost Spy evs))";
   349 by (etac tls.induct 1);
   348 by (etac tls.induct 1);
   350 by (ClientCertKeyEx_tac 6);
   349 by (ClientCertKeyEx_tac 6);
   351 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   350 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   352 by (REPEAT_FIRST (rtac lemma ));
   351 by (REPEAT_FIRST (rtac lemma));
   353 	(*SLOW: 30s!*)
   352 writeln"SLOW simplification: 50 secs!??";
   354 by (ALLGOALS (asm_simp_tac analz_image_keys_ss));
   353 by (ALLGOALS
   355 by (ALLGOALS (asm_simp_tac
   354     (asm_simp_tac (analz_image_keys_ss 
   356 	      (!simpset addsimps [analz_image_priK, insert_absorb])));
   355 		   addsimps (analz_image_priK::certificate_def::
       
   356 			     keys_distinct))));
       
   357 by (ALLGOALS (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_priK])));
       
   358 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb])));
   357 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*)
   359 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*)
   358 by (Blast_tac 3);
   360 by (Blast_tac 3);
   359 (*Fake*) 
   361 (*Fake*) 
   360 by (spy_analz_tac 2);
   362 by (spy_analz_tac 2);
   361 (*Base*)
   363 (*Base*)
   362 by (Blast_tac 1);
   364 by (Blast_tac 1);
   363 qed_spec_mp "analz_image_keys";
   365 qed_spec_mp "analz_image_keys";
   364 
   366 
   365 
   367 
   366 (*If A sends ClientCertKeyEx to an uncompromised B, then M will stay secret.
   368 (*If A sends ClientCertKeyEx to an uncompromised B, then M will stay secret.*)
   367   The assumption is A~=Spy, not A~:lost, since A doesn't use her private key
   369 goal thy
   368   here.*)
   370  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]           \
   369 goalw thy [certificate_def]
   371 \        ==> Notes A {|Agent B, Nonce M|} : set evs  -->   \
   370  "!!evs. [| evs : tls;  A~=Spy;  B ~: lost |]                        \
   372 \            Nonce M ~: analz (sees lost Spy evs)";
   371 \        ==> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} \
       
   372 \              : set evs  -->  Nonce M ~: analz (sees lost Spy evs)";
       
   373 by (analz_induct_tac 1);
   373 by (analz_induct_tac 1);
   374 (*ClientHello*)
   374 (*ClientHello*)
   375 by (blast_tac (!claset addSEs sees_Spy_partsEs) 3);
   375 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   376                                addSEs sees_Spy_partsEs) 3);
   376 (*SpyKeys*)
   377 (*SpyKeys*)
   377 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   378 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   378 (*Fake*)
   379 (*Fake*)
   379 by (spy_analz_tac 1);
   380 by (spy_analz_tac 1);
   380 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
   381 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
   381 by (REPEAT (blast_tac (!claset addSEs partsEs
   382 by (REPEAT (blast_tac (!claset addSEs partsEs
   382 			       addDs  [impOfSubs analz_subset_parts,
   383 			       addDs  [Notes_Crypt_parts_sees,
       
   384 				       impOfSubs analz_subset_parts,
   383 				       Says_imp_sees_Spy' RS analz.Inj]) 1));
   385 				       Says_imp_sees_Spy' RS analz.Inj]) 1));
   384 bind_thm ("Spy_not_see_premaster_secret", result() RSN (2, rev_mp));
   386 bind_thm ("Spy_not_see_premaster_secret", result() RSN (2, rev_mp));
   385 
   387 
   386 
   388 
   387 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***)
   389 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***)
   388 
   390 
   389 (*The two proofs are identical*)
   391 (** First, some lemmas about those write keys.  The proofs for serverK are 
   390 goal thy 
   392     nearly identical to those for clientK. **)
   391  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  \
   393 
   392 \           evs : tls |]                           \
   394 (*Lemma: those write keys are never sent if M is secure.  
       
   395   Converse doesn't hold; betraying M doesn't force the keys to be sent!*)
       
   396 
       
   397 goal thy 
       
   398  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  evs : tls |]   \
   393 \        ==> Key (clientK(NA,NB,M)) ~: parts (sees lost Spy evs)";
   399 \        ==> Key (clientK(NA,NB,M)) ~: parts (sees lost Spy evs)";
   394 by (etac rev_mp 1);
   400 by (etac rev_mp 1);
   395 by (analz_induct_tac 1);
   401 by (analz_induct_tac 1);
   396 (*SpyKeys*)
   402 (*SpyKeys*)
   397 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
   403 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
   400 by (spy_analz_tac 2);
   406 by (spy_analz_tac 2);
   401 (*Base*)
   407 (*Base*)
   402 by (Blast_tac 1);
   408 by (Blast_tac 1);
   403 qed "clientK_notin_parts";
   409 qed "clientK_notin_parts";
   404 
   410 
   405 goal thy 
   411 Addsimps [clientK_notin_parts];
   406  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  \
   412 AddSEs [clientK_notin_parts RSN (2, rev_notE)];
   407 \           evs : tls |]                           \
   413 
       
   414 goal thy 
       
   415  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  evs : tls |]   \
   408 \        ==> Key (serverK(NA,NB,M)) ~: parts (sees lost Spy evs)";
   416 \        ==> Key (serverK(NA,NB,M)) ~: parts (sees lost Spy evs)";
   409 by (etac rev_mp 1);
   417 by (etac rev_mp 1);
   410 by (analz_induct_tac 1);
   418 by (analz_induct_tac 1);
   411 (*SpyKeys*)
   419 (*SpyKeys*)
   412 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
   420 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
   415 by (spy_analz_tac 2);
   423 by (spy_analz_tac 2);
   416 (*Base*)
   424 (*Base*)
   417 by (Blast_tac 1);
   425 by (Blast_tac 1);
   418 qed "serverK_notin_parts";
   426 qed "serverK_notin_parts";
   419 
   427 
       
   428 Addsimps [serverK_notin_parts];
       
   429 AddSEs [serverK_notin_parts RSN (2, rev_notE)];
       
   430 
       
   431 (*Lemma: those write keys are never used if M is fresh.  
       
   432   Converse doesn't hold; betraying M doesn't force the keys to be sent!
       
   433   NOT suitable as safe elim rules.*)
       
   434 
       
   435 goal thy 
       
   436  "!!evs. [| Nonce M ~: used evs;  evs : tls |]                           \
       
   437 \        ==> Crypt (clientK(NA,NB,M)) Y ~: parts (sees lost Spy evs)";
       
   438 by (etac rev_mp 1);
       
   439 by (analz_induct_tac 1);
       
   440 (*ClientFinished: since M is fresh, a different instance of clientK was used.*)
       
   441 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   442                                addSEs sees_Spy_partsEs) 3);
       
   443 by (Fake_parts_insert_tac 2);
       
   444 (*Base*)
       
   445 by (Blast_tac 1);
       
   446 qed "Crypt_clientK_notin_parts";
       
   447 
       
   448 Addsimps [Crypt_clientK_notin_parts];
       
   449 AddEs [Crypt_clientK_notin_parts RSN (2, rev_notE)];
       
   450 
       
   451 goal thy 
       
   452  "!!evs. [| Nonce M ~: used evs;  evs : tls |]                           \
       
   453 \        ==> Crypt (serverK(NA,NB,M)) Y ~: parts (sees lost Spy evs)";
       
   454 by (etac rev_mp 1);
       
   455 by (analz_induct_tac 1);
       
   456 (*ServerFinished: since M is fresh, a different instance of serverK was used.*)
       
   457 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   458                                addSEs sees_Spy_partsEs) 3);
       
   459 by (Fake_parts_insert_tac 2);
       
   460 (*Base*)
       
   461 by (Blast_tac 1);
       
   462 qed "Crypt_serverK_notin_parts";
       
   463 
       
   464 Addsimps [Crypt_serverK_notin_parts];
       
   465 AddEs [Crypt_serverK_notin_parts RSN (2, rev_notE)];
       
   466 
       
   467 
       
   468 (*Weakening A~:lost to A~=Spy would complicate later uses of the rule*)
       
   469 goal thy
       
   470  "!!evs. [| Says A B {|certA, Crypt KB (Nonce M)|} : set evs;   \
       
   471 \           A ~: lost;  evs : tls |] ==> KB = pubK B";
       
   472 be rev_mp 1;
       
   473 by (analz_induct_tac 1);
       
   474 qed "A_Crypt_pubB";
       
   475 
       
   476 
       
   477 (*** Unicity results for M, the pre-master-secret ***)
       
   478 
       
   479 (*Induction for theorems of the form X ~: analz (sees lost Spy evs) --> ...
       
   480   It simplifies the proof by discarding needless information about
       
   481 	analz (insert X (sees lost Spy evs)) 
       
   482 *)
       
   483 fun analz_mono_parts_induct_tac i = 
       
   484     etac tls.induct i           THEN 
       
   485     ClientCertKeyEx_tac  (i+5)  THEN	(*ClientCertKeyEx*)
       
   486     REPEAT_FIRST analz_mono_contra_tac;
       
   487 
       
   488 
       
   489 (*M determines B.  Proof borrowed from NS_Public/unique_NA and from Yahalom*)
       
   490 goal thy 
       
   491  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  evs : tls |]   \
       
   492 \        ==> EX B'. ALL B.   \
       
   493 \              Crypt (pubK B) (Nonce M) : parts (sees lost Spy evs) --> B=B'";
       
   494 by (etac rev_mp 1);
       
   495 by (analz_mono_parts_induct_tac 1);
       
   496 by (prove_simple_subgoals_tac 1);
       
   497 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]
       
   498                            setloop split_tac [expand_if]) 2);
       
   499 (*ClientCertKeyEx*)
       
   500 by (expand_case_tac "M = ?y" 2 THEN
       
   501     REPEAT (blast_tac (!claset addSEs partsEs) 2));
       
   502 by (Fake_parts_insert_tac 1);
       
   503 val lemma = result();
       
   504 
       
   505 goal thy 
       
   506  "!!evs. [| Crypt(pubK B)  (Nonce M) : parts (sees lost Spy evs); \
       
   507 \           Crypt(pubK B') (Nonce M) : parts (sees lost Spy evs); \
       
   508 \           Nonce M ~: analz (sees lost Spy evs);                 \
       
   509 \           evs : tls |]                                          \
       
   510 \        ==> B=B'";
       
   511 by (prove_unique_tac lemma 1);
       
   512 qed "unique_M";
       
   513 
       
   514 
       
   515 (*In A's note to herself, M determines A and B.*)
       
   516 goal thy 
       
   517  "!!evs. [| Nonce M ~: analz (sees lost Spy evs);  evs : tls |]            \
       
   518 \ ==> EX A' B'. ALL A B.                                                   \
       
   519 \        Notes A {|Agent B, Nonce M|} : set evs --> A=A' & B=B'";
       
   520 by (etac rev_mp 1);
       
   521 by (analz_mono_parts_induct_tac 1);
       
   522 by (prove_simple_subgoals_tac 1);
       
   523 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1);
       
   524 (*ClientCertKeyEx: if M is fresh, then it can't appear in Notes A X.*)
       
   525 by (expand_case_tac "M = ?y" 1 THEN
       
   526     blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1);
       
   527 val lemma = result();
       
   528 
       
   529 goal thy 
       
   530  "!!evs. [| Notes A  {|Agent B,  Nonce M|} : set evs;  \
       
   531 \           Notes A' {|Agent B', Nonce M|} : set evs;  \
       
   532 \           Nonce M ~: analz (sees lost Spy evs);      \
       
   533 \           evs : tls |]                               \
       
   534 \        ==> A=A' & B=B'";
       
   535 by (prove_unique_tac lemma 1);
       
   536 qed "Notes_unique_M";
       
   537 
       
   538 
   420 
   539 
   421 (*** Protocol goals: if A receives SERVER FINISHED, then B is present 
   540 (*** Protocol goals: if A receives SERVER FINISHED, then B is present 
   422      and has used the quoted values XA, XB, etc.  Note that it is up to A
   541      and has used the quoted values XA, XB, etc.  Note that it is up to A
   423      to compare XA with what she originally sent.
   542      to compare XA with what she originally sent.
   424 ***)
   543 ***)
   425 
   544 
   426 goalw thy [certificate_def]
   545 (*The mention of her name (A) in X assumes A that B knows who she is.*)
   427  "!!evs. [| X = Crypt (serverK(NA,NB,M))                            \
   546 goal thy
   428 \                 (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|},       \
   547  "!!evs. [| X = Crypt (serverK(NA,NB,M))                                \
   429 \                        Nonce NA, Agent XA, Agent A,               \
   548 \                 (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|},           \
       
   549 \                        Nonce NA, Agent XA, Agent A,                   \
   430 \                        Nonce NB, Agent XB, certificate B (pubK B)|}); \
   550 \                        Nonce NB, Agent XB, certificate B (pubK B)|}); \
   431 \           evs : tls;  A~=Spy;  B ~: lost |]                       \
   551 \           evs : tls;  A ~: lost;  B ~: lost |]                        \
   432 \    ==> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} \
   552 \        ==> Notes A {|Agent B, Nonce M|} : set evs -->                 \
   433 \          : set evs -->              \
       
   434 \        X : parts (sees lost Spy evs) --> Says B A X : set evs";
   553 \        X : parts (sees lost Spy evs) --> Says B A X : set evs";
   435 by (hyp_subst_tac 1);
   554 by (hyp_subst_tac 1);
   436 by (etac tls.induct 1);
   555 by (analz_induct_tac 1);
   437 by (ALLGOALS Asm_simp_tac);
   556 by (REPEAT_FIRST (rtac impI));
   438 (*ClientCertKeyEx: M isn't in the Hash because it's fresh!*)
       
   439 by (blast_tac (!claset addSDs [Hash_Hash_imp_Nonce]
       
   440                        addSEs sees_Spy_partsEs) 2);
       
   441 (*Fake: the Spy doesn't have the critical session key!*)
   557 (*Fake: the Spy doesn't have the critical session key!*)
   442 by (REPEAT (rtac impI 1));
   558 by (REPEAT (rtac impI 1));
   443 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1);
   559 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1);
   444 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, 
   560 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, 
   445 				     serverK_notin_parts, 
       
   446 				     not_parts_not_analz]) 2);
   561 				     not_parts_not_analz]) 2);
   447 by (Fake_parts_insert_tac 1);
   562 by (Fake_parts_insert_tac 1);
   448 qed_spec_mp "TrustServerFinished";
   563 qed_spec_mp "TrustServerFinished";
   449 
   564 
   450 
   565 
   451 (*** Protocol goal: if B receives CLIENT FINISHED, then A has used the
   566 (*This version refers not to SERVER FINISHED but to any message from B.
   452      quoted values XA, XB, etc., which B can then check.  BUT NOTE:
   567   We don't assume B has received CERTIFICATE VERIFY, and an intruder could
   453      B has no way of knowing that A is the sender of CLIENT CERTIFICATE!
   568   have changed A's identity in all other messages, so we can't be sure
       
   569   that B sends his message to A.*)
       
   570 goal thy
       
   571  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]                         \
       
   572 \        ==> Notes A {|Agent B, Nonce M|} : set evs -->                  \
       
   573 \            Crypt (serverK(NA,NB,M)) Y : parts (sees lost Spy evs)  --> \
       
   574 \            (EX A'. Says B A' (Crypt (serverK(NA,NB,M)) Y) : set evs)";
       
   575 by (analz_induct_tac 1);
       
   576 by (REPEAT_FIRST (rtac impI));
       
   577 (*Fake: the Spy doesn't have the critical session key!*)
       
   578 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1);
       
   579 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, 
       
   580 				     not_parts_not_analz]) 2);
       
   581 by (Fake_parts_insert_tac 1);
       
   582 (*ServerFinished.  If the message is old then apply induction hypothesis...*)
       
   583 by (rtac conjI 1 THEN Blast_tac 2);
       
   584 (*...otherwise delete induction hyp and use unicity of M.*)
       
   585 by (thin_tac "?PP-->?QQ" 1);
       
   586 by (Step_tac 1);
       
   587 by (subgoal_tac "Nonce M ~: analz (sees lost Spy evsa)" 1);
       
   588 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2);
       
   589 by (blast_tac (!claset addSEs [MPair_parts]
       
   590 		       addDs  [Notes_Crypt_parts_sees,
       
   591 			       Says_imp_sees_Spy' RS parts.Inj,
       
   592 			       unique_M]) 1);
       
   593 qed_spec_mp "TrustServerMsg";
       
   594 
       
   595 
       
   596 (*** Protocol goal: if B receives any message encrypted with clientK
       
   597      then A has sent it, ASSUMING that A chose M.  Authentication is
       
   598      assumed here; B cannot verify it.  But if the message is
       
   599      CLIENT FINISHED, then B can then check the quoted values XA, XB, etc.
   454 ***)
   600 ***)
   455 goalw thy [certificate_def]
   601 goal thy
   456  "!!evs. [| X = Crypt (clientK(NA,NB,M))                        \
   602  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]                         \
   457 \                 (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|},   \
   603 \        ==> Notes A {|Agent B, Nonce M|} : set evs -->                  \
   458 \                        Nonce NA, Agent XA,                    \
   604 \            Crypt (clientK(NA,NB,M)) Y : parts (sees lost Spy evs) -->  \
   459 \                        certificate A (pubK A),                \
   605 \            Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs";
   460 \                        Nonce NB, Agent XB, Agent B|});        \
   606 by (analz_induct_tac 1);
   461 \           evs : tls;  A~=Spy;  B ~: lost |]                   \
   607 by (REPEAT_FIRST (rtac impI));
   462 \     ==> Says A B {|certificate A (pubK A),                    \
       
   463 \                    Crypt KB (Nonce M)|} : set evs -->         \
       
   464 \         X : parts (sees lost Spy evs) --> Says A B X : set evs";
       
   465 by (hyp_subst_tac 1);
       
   466 by (etac tls.induct 1);
       
   467 by (ALLGOALS Asm_simp_tac);
       
   468 (*ClientCertKeyEx: M isn't in the Hash because it's fresh!*)
       
   469 by (blast_tac (!claset addSDs [Hash_Hash_imp_Nonce]
       
   470                        addSEs sees_Spy_partsEs) 2);
       
   471 (*Fake: the Spy doesn't have the critical session key!*)
   608 (*Fake: the Spy doesn't have the critical session key!*)
   472 by (REPEAT (rtac impI 1));
       
   473 by (subgoal_tac "Key (clientK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1);
   609 by (subgoal_tac "Key (clientK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1);
   474 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, 
   610 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, 
   475 				     clientK_notin_parts, 
       
   476 				     not_parts_not_analz]) 2);
   611 				     not_parts_not_analz]) 2);
   477 by (Fake_parts_insert_tac 1);
   612 by (Fake_parts_insert_tac 1);
   478 qed_spec_mp "TrustClientFinished";
   613 (*ClientFinished.  If the message is old then apply induction hypothesis...*)
       
   614 by (step_tac (!claset delrules [conjI]) 1);
       
   615 by (subgoal_tac "Nonce M ~: analz (sees lost Spy evsa)" 1);
       
   616 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2);
       
   617 by (blast_tac (!claset addSEs [MPair_parts]
       
   618 		       addDs  [Notes_unique_M]) 1);
       
   619 qed_spec_mp "TrustClientMsg";
   479 
   620 
   480 
   621 
   481 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to
   622 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to
   482      check a CERTIFICATE VERIFY from A, then A has used the quoted
   623      check a CERTIFICATE VERIFY from A, then A has used the quoted
   483      values XA, XB, etc.  Even this one requires A to be uncompromised.
   624      values XA, XB, etc.  Even this one requires A to be uncompromised.
   484  ***)
   625  ***)
   485 goal thy
   626 goal thy
   486  "!!evs. [| X = Crypt (clientK(NA,NB,M))                        \
   627  "!!evs. [| Says A' B (Crypt (clientK(NA,NB,M)) Y) : set evs;             \
   487 \                 (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|},   \
   628 \           Says B  A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|}  \
   488 \                        Nonce NA, Agent XA,                    \
   629 \             : set evs;                                                  \
   489 \                        certificate A (pubK A),                \
   630 \           Says A'' B (Crypt (priK A)                                    \
   490 \                        Nonce NB, Agent XB, Agent B|});        \
   631 \                       (Hash{|Nonce NB, certificate B KB, Nonce M|}))    \
   491 \           Says A' B X : set evs;                              \
   632 \             : set evs;                                                  \
   492 \           Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|}  \
   633 \        evs : tls;  A ~: lost;  B ~: lost |]                             \
   493 \             : set evs;                                        \
   634 \     ==> Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs";
   494 \           Says A'' B (Crypt (priK A)                                   \
   635 by (blast_tac (!claset addSIs [TrustClientMsg, UseCertVerify]
   495 \                       (Hash{|Nonce NB, certificate B KB, Nonce M|}))   \
   636                        addDs  [Says_imp_sees_Spy RS parts.Inj]) 1);
   496 \             : set evs;                                        \
   637 qed "AuthClientFinished";
   497 \        evs : tls;  A ~: lost;  B ~: lost |]                   \
       
   498 \     ==> Says A B X : set evs";
       
   499 br TrustClientFinished 1;
       
   500 br (TrustCertVerify RS UseCertVerify) 5;
       
   501 by (REPEAT_FIRST (ares_tac [refl]));
       
   502 by (ALLGOALS 
       
   503     (asm_full_simp_tac (!simpset addsimps [Says_imp_sees_Spy RS parts.Inj])));
       
   504 qed_spec_mp "AuthClientFinished";