src/HOL/Auth/TLS.ML
changeset 3677 f2569416d18b
parent 3676 cbaec955056b
child 3683 aafe719dff14
equal deleted inserted replaced
3676:cbaec955056b 3677:f2569416d18b
    46 qed "eq_certificate_iff";
    46 qed "eq_certificate_iff";
    47 AddIffs [eq_certificate_iff];
    47 AddIffs [eq_certificate_iff];
    48 
    48 
    49 
    49 
    50 (*Injectiveness of key-generating functions*)
    50 (*Injectiveness of key-generating functions*)
    51 AddIffs [inj_PRF RS inj_eq, inj_clientK RS inj_eq, inj_serverK RS inj_eq];
    51 AddIffs [inj_PRF RS inj_eq, inj_sessionK RS inj_eq];
    52 
    52 
    53 (* invKey(clientK x) = clientK x  and similarly for serverK*)
    53 (* invKey(sessionK x) = sessionK x*)
    54 Addsimps [isSym_clientK, rewrite_rule [isSymKey_def] isSym_clientK,
    54 Addsimps [isSym_sessionK, rewrite_rule [isSymKey_def] isSym_sessionK];
    55 	  isSym_serverK, rewrite_rule [isSymKey_def] isSym_serverK];
       
    56 
    55 
    57 
    56 
    58 (*** clientK and serverK make symmetric keys; no clashes with pubK or priK ***)
    57 (*** clientK and serverK make symmetric keys; no clashes with pubK or priK ***)
    59 
    58 
    60 goal thy "pubK A ~= clientK arg";
    59 goal thy "pubK A ~= sessionK arg";
    61 br notI 1;
    60 br notI 1;
    62 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
    61 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
    63 by (Full_simp_tac 1);
    62 by (Full_simp_tac 1);
    64 qed "pubK_neq_clientK";
    63 qed "pubK_neq_sessionK";
    65 
    64 
    66 goal thy "pubK A ~= serverK arg";
    65 goal thy "priK A ~= sessionK arg";
    67 br notI 1;
    66 br notI 1;
    68 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
    67 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
    69 by (Full_simp_tac 1);
    68 by (Full_simp_tac 1);
    70 qed "pubK_neq_serverK";
    69 qed "priK_neq_sessionK";
    71 
    70 
    72 goal thy "priK A ~= clientK arg";
    71 val keys_distinct = [pubK_neq_sessionK, priK_neq_sessionK];
    73 br notI 1;
       
    74 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
       
    75 by (Full_simp_tac 1);
       
    76 qed "priK_neq_clientK";
       
    77 
       
    78 goal thy "priK A ~= serverK arg";
       
    79 br notI 1;
       
    80 by (dres_inst_tac [("f","isSymKey")] arg_cong 1);
       
    81 by (Full_simp_tac 1);
       
    82 qed "priK_neq_serverK";
       
    83 
       
    84 (*clientK and serverK have disjoint ranges*)
       
    85 goal thy "clientK arg ~= serverK arg'";
       
    86 by (cut_facts_tac [rangeI RS impOfSubs clientK_range] 1);
       
    87 by (Blast_tac 1);
       
    88 qed "clientK_neq_serverK";
       
    89 
       
    90 val keys_distinct = [pubK_neq_clientK, pubK_neq_serverK, 
       
    91 		     priK_neq_clientK, priK_neq_serverK, clientK_neq_serverK];
       
    92 AddIffs (keys_distinct @ (keys_distinct RL [not_sym]));
    72 AddIffs (keys_distinct @ (keys_distinct RL [not_sym]));
    93 
    73 
    94 
    74 
    95 (**** Protocol Proofs ****)
    75 (**** Protocol Proofs ****)
    96 
    76 
   261 by (analz_induct_tac 1);
   241 by (analz_induct_tac 1);
   262 by (blast_tac (!claset addIs [parts_insertI]) 1);
   242 by (blast_tac (!claset addIs [parts_insertI]) 1);
   263 qed "Notes_Crypt_parts_sees";
   243 qed "Notes_Crypt_parts_sees";
   264 
   244 
   265 
   245 
   266 (*****************
       
   267     (*NEEDED?  TRUE???
       
   268       Every Nonce that's hashed is already in past traffic. 
       
   269       This general formulation is tricky to prove and hard to use, since the
       
   270       2nd premise is typically proved by simplification.*)
       
   271     goal thy "!!evs. [| Hash X : parts (sees Spy evs);  \
       
   272     \                   Nonce N : parts {X};  evs : tls |]  \
       
   273     \                ==> Nonce N : parts (sees Spy evs)";
       
   274     by (etac rev_mp 1);
       
   275     by (parts_induct_tac 1);
       
   276     by (step_tac (!claset addSDs [Notes_Crypt_parts_sees,
       
   277 				  Says_imp_sees_Spy RS parts.Inj]
       
   278 			  addSEs partsEs) 1);
       
   279     by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [parts_insert_sees])));
       
   280     by (Fake_parts_insert_tac 1);
       
   281     (*CertVerify, ClientFinished, ServerFinished (?)*)
       
   282     by (REPEAT (Blast_tac 1));
       
   283     qed "Hash_imp_Nonce_seen";
       
   284 ****************************************************************)
       
   285 
       
   286 
       
   287 (*** Protocol goal: if B receives CERTIFICATE VERIFY, then A sent it ***)
   246 (*** Protocol goal: if B receives CERTIFICATE VERIFY, then A sent it ***)
   288 
   247 
   289 (*B can check A's signature if he has received A's certificate.
   248 (*B can check A's signature if he has received A's certificate.
   290   Perhaps B~=Spy is unnecessary, but there's no obvious proof if the first
   249   Perhaps B~=Spy is unnecessary, but there's no obvious proof if the first
   291   message is Fake.  We don't need guarantees for the Spy anyway.  We must
   250   message is Fake.  We don't need guarantees for the Spy anyway.  We must
   324 \  ALL KK. (Key(priK B) : analz (Key``KK Un (sees Spy evs))) =  \
   283 \  ALL KK. (Key(priK B) : analz (Key``KK Un (sees Spy evs))) =  \
   325 \            (priK B : KK | B : lost)";
   284 \            (priK B : KK | B : lost)";
   326 by (etac tls.induct 1);
   285 by (etac tls.induct 1);
   327 by (ALLGOALS
   286 by (ALLGOALS
   328     (asm_simp_tac (analz_image_keys_ss
   287     (asm_simp_tac (analz_image_keys_ss
   329 		   addsimps (certificate_def::keys_distinct))));
   288 		   addsimps (analz_insert_certificate::keys_distinct))));
   330 (*Fake*) 
   289 (*Fake*) 
   331 by (spy_analz_tac 2);
   290 by (spy_analz_tac 2);
   332 (*Base*)
   291 (*Base*)
   333 by (Blast_tac 1);
   292 by (Blast_tac 1);
   334 qed_spec_mp "analz_image_priK";
   293 qed_spec_mp "analz_image_priK";
   339  "!!evs. (X : analz (G Un H)) --> (X : analz H)  ==> \
   298  "!!evs. (X : analz (G Un H)) --> (X : analz H)  ==> \
   340 \        (X : analz (G Un H))  =  (X : analz H)";
   299 \        (X : analz (G Un H))  =  (X : analz H)";
   341 by (blast_tac (!claset addIs [impOfSubs analz_mono]) 1);
   300 by (blast_tac (!claset addIs [impOfSubs analz_mono]) 1);
   342 val lemma = result();
   301 val lemma = result();
   343 
   302 
   344 (*Knowing some clientKs and serverKs is no help in getting new nonces*)
   303 (*slightly speeds up the big simplification below*)
       
   304 goal thy "!!evs. KK <= range sessionK ==> priK B ~: KK";
       
   305 by (Blast_tac 1);
       
   306 val range_sessionkeys_not_priK = result();
       
   307 
       
   308 (*Knowing some session keys is no help in getting new nonces*)
   345 goal thy  
   309 goal thy  
   346  "!!evs. evs : tls ==>                                 \
   310  "!!evs. evs : tls ==>                                 \
   347 \    ALL KK. KK <= (range clientK Un range serverK) -->           \
   311 \    ALL KK. KK <= range sessionK -->           \
   348 \            (Nonce N : analz (Key``KK Un (sees Spy evs))) = \
   312 \            (Nonce N : analz (Key``KK Un (sees Spy evs))) = \
   349 \            (Nonce N : analz (sees Spy evs))";
   313 \            (Nonce N : analz (sees Spy evs))";
   350 by (etac tls.induct 1);
   314 by (etac tls.induct 1);
   351 by (ClientCertKeyEx_tac 6);
   315 by (ClientCertKeyEx_tac 6);
   352 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   316 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   353 by (REPEAT_FIRST (rtac lemma));
   317 by (REPEAT_FIRST (rtac lemma));
   354 writeln"SLOW simplification: 60 secs!??";
   318 writeln"SLOW simplification: 55 secs??";
       
   319 (*ClientCertKeyEx is to blame, causing case splits for A, B: lost*)
   355 by (ALLGOALS
   320 by (ALLGOALS
   356     (asm_simp_tac (analz_image_keys_ss 
   321     (asm_simp_tac (analz_image_keys_ss 
   357 		   addsimps (analz_image_priK::certificate_def::
   322 		   addsimps [range_sessionkeys_not_priK, 
   358                              keys_distinct))));
   323 			     analz_image_priK, analz_insert_certificate])));
   359 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb])));
   324 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb])));
   360 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*)
       
   361 by (Blast_tac 3);
       
   362 (*Fake*) 
   325 (*Fake*) 
   363 by (spy_analz_tac 2);
   326 by (spy_analz_tac 2);
   364 (*Base*)
   327 (*Base*)
   365 by (Blast_tac 1);
   328 by (Blast_tac 1);
   366 qed_spec_mp "analz_image_keys";
   329 qed_spec_mp "analz_image_keys";
   372 by (Blast_tac 1);
   335 by (Blast_tac 1);
   373 qed "no_Notes_A_PRF";
   336 qed "no_Notes_A_PRF";
   374 Addsimps [no_Notes_A_PRF];
   337 Addsimps [no_Notes_A_PRF];
   375 
   338 
   376 
   339 
       
   340 goal thy "!!evs. [| Nonce (PRF (PMS,NA,NB)) : parts (sees Spy evs);  \
       
   341 \                   evs : tls |]  \
       
   342 \                ==> Nonce PMS : parts (sees Spy evs)";
       
   343 by (etac rev_mp 1);
       
   344 by (parts_induct_tac 1);
       
   345 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees])));
       
   346 by (Fake_parts_insert_tac 1);
       
   347 (*Six others, all trivial or by freshness*)
       
   348 by (REPEAT (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   349                                addSEs sees_Spy_partsEs) 1));
       
   350 qed "MS_imp_PMS";
       
   351 AddSDs [MS_imp_PMS];
       
   352 
       
   353 
       
   354 
       
   355 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***)
       
   356 
       
   357 (** Some lemmas about session keys, comprising clientK and serverK **)
       
   358 
       
   359 (*Lemma: those write keys are never sent if M (MASTER SECRET) is secure.  
       
   360   Converse doesn't hold; betraying M doesn't force the keys to be sent!*)
       
   361 
       
   362 goal thy 
       
   363  "!!evs. [| Nonce M ~: analz (sees Spy evs);  evs : tls |]   \
       
   364 \        ==> Key (sessionK(b,NA,NB,M)) ~: parts (sees Spy evs)";
       
   365 by (etac rev_mp 1);
       
   366 by (analz_induct_tac 1);
       
   367 (*SpyKeys*)
       
   368 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
       
   369 by (blast_tac (!claset addDs [Says_imp_sees_Spy RS analz.Inj]) 3);
       
   370 (*Fake*) 
       
   371 by (spy_analz_tac 2);
       
   372 (*Base*)
       
   373 by (Blast_tac 1);
       
   374 qed "sessionK_notin_parts";
       
   375 bind_thm ("sessionK_in_partsE", sessionK_notin_parts RSN (2, rev_notE));
       
   376 
       
   377 Addsimps [sessionK_notin_parts];
       
   378 AddSEs [sessionK_in_partsE, 
       
   379 	impOfSubs analz_subset_parts RS sessionK_in_partsE];
       
   380 
       
   381 
       
   382 (*Lemma: session keys are never used if PMS is fresh.  
       
   383   Nonces don't have to agree, allowing session resumption.
       
   384   Converse doesn't hold; revealing PMS doesn't force the keys to be sent.
       
   385   They are NOT suitable as safe elim rules.*)
       
   386 
       
   387 goal thy 
       
   388  "!!evs. [| Nonce PMS ~: parts (sees Spy evs);  evs : tls |]             \
       
   389 \  ==> Crypt (sessionK(b, Na, Nb, PRF(PMS,NA,NB))) Y ~: parts (sees Spy evs)";
       
   390 by (etac rev_mp 1);
       
   391 by (analz_induct_tac 1);
       
   392 (*Fake*)
       
   393 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 2);
       
   394 by (Fake_parts_insert_tac 2);
       
   395 (*Base, ClientFinished, ServerFinished: trivial, e.g. by freshness*)
       
   396 by (REPEAT 
       
   397     (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   398                         addSEs sees_Spy_partsEs) 1));
       
   399 qed "Crypt_sessionK_notin_parts";
       
   400 
       
   401 Addsimps [Crypt_sessionK_notin_parts];
       
   402 AddEs [Crypt_sessionK_notin_parts RSN (2, rev_notE)];
       
   403 
       
   404 
       
   405 (*NEEDED??*)
       
   406 goal thy
       
   407  "!!evs. [| Says A B {|certA, Crypt KB (Nonce M)|} : set evs;   \
       
   408 \           A ~= Spy;  evs : tls |] ==> KB = pubK B";
       
   409 be rev_mp 1;
       
   410 by (analz_induct_tac 1);
       
   411 qed "A_Crypt_pubB";
       
   412 
       
   413 
       
   414 (*** Unicity results for PMS, the pre-master-secret ***)
       
   415 
       
   416 (*PMS determines B.  Proof borrowed from NS_Public/unique_NA and from Yahalom*)
       
   417 goal thy 
       
   418  "!!evs. [| Nonce PMS ~: analz (sees Spy evs);  evs : tls |]   \
       
   419 \        ==> EX B'. ALL B.   \
       
   420 \              Crypt (pubK B) (Nonce PMS) : parts (sees Spy evs) --> B=B'";
       
   421 by (etac rev_mp 1);
       
   422 by (parts_induct_tac 1);
       
   423 by (Fake_parts_insert_tac 1);
       
   424 (*ClientCertKeyEx*)
       
   425 by (ClientCertKeyEx_tac 1);
       
   426 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1);
       
   427 by (expand_case_tac "PMS = ?y" 1 THEN
       
   428     blast_tac (!claset addSEs partsEs) 1);
       
   429 val lemma = result();
       
   430 
       
   431 goal thy 
       
   432  "!!evs. [| Crypt(pubK B)  (Nonce PMS) : parts (sees Spy evs); \
       
   433 \           Crypt(pubK B') (Nonce PMS) : parts (sees Spy evs); \
       
   434 \           Nonce PMS ~: analz (sees Spy evs);                 \
       
   435 \           evs : tls |]                                          \
       
   436 \        ==> B=B'";
       
   437 by (prove_unique_tac lemma 1);
       
   438 qed "unique_PMS";
       
   439 
       
   440 
       
   441 (*In A's internal Note, PMS determines A and B.*)
       
   442 goal thy 
       
   443  "!!evs. [| Nonce PMS ~: analz (sees Spy evs);  evs : tls |]            \
       
   444 \ ==> EX A' B'. ALL A B.                                                   \
       
   445 \        Notes A {|Agent B, Nonce PMS|} : set evs --> A=A' & B=B'";
       
   446 by (etac rev_mp 1);
       
   447 by (parts_induct_tac 1);
       
   448 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1);
       
   449 (*ClientCertKeyEx: if PMS is fresh, then it can't appear in Notes A X.*)
       
   450 by (expand_case_tac "PMS = ?y" 1 THEN
       
   451     blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1);
       
   452 val lemma = result();
       
   453 
       
   454 goal thy 
       
   455  "!!evs. [| Notes A  {|Agent B,  Nonce PMS|} : set evs;  \
       
   456 \           Notes A' {|Agent B', Nonce PMS|} : set evs;  \
       
   457 \           Nonce PMS ~: analz (sees Spy evs);      \
       
   458 \           evs : tls |]                               \
       
   459 \        ==> A=A' & B=B'";
       
   460 by (prove_unique_tac lemma 1);
       
   461 qed "Notes_unique_PMS";
       
   462 
       
   463 
       
   464 
   377 (*If A sends ClientCertKeyEx to an honest B, then the PMS will stay secret.*)
   465 (*If A sends ClientCertKeyEx to an honest B, then the PMS will stay secret.*)
   378 goal thy
   466 goal thy
   379  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]           \
   467  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]           \
   380 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   468 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   381 \            Nonce PMS ~: analz (sees Spy evs)";
   469 \            Nonce PMS ~: analz (sees Spy evs)";
   382 by (analz_induct_tac 1);   (*47 seconds???*)
   470 by (analz_induct_tac 1);   (*30 seconds???*)
       
   471 (*ClientAccepts and ServerAccepts: because PMS ~: range PRF*)
       
   472 by (REPEAT (fast_tac (!claset addss (!simpset)) 6));
       
   473 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
       
   474 by (REPEAT (blast_tac (!claset addSEs partsEs
       
   475 			       addDs  [Notes_Crypt_parts_sees,
       
   476 				       impOfSubs analz_subset_parts,
       
   477 				       Says_imp_sees_Spy RS analz.Inj]) 4));
   383 (*ClientHello*)
   478 (*ClientHello*)
   384 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
   479 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
   385                                addSEs sees_Spy_partsEs) 3);
   480                                addSEs sees_Spy_partsEs) 3);
   386 (*SpyKeys*)
   481 (*SpyKeys*)
   387 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   482 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   388 by (fast_tac (!claset addss (!simpset)) 2);
   483 by (fast_tac (!claset addss (!simpset)) 2);
   389 (*Fake*)
   484 (*Fake*)
   390 by (spy_analz_tac 1);
   485 by (spy_analz_tac 1);
   391 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
       
   392 by (REPEAT (blast_tac (!claset addSEs partsEs
       
   393 			       addDs  [Notes_Crypt_parts_sees,
       
   394 				       impOfSubs analz_subset_parts,
       
   395 				       Says_imp_sees_Spy RS analz.Inj]) 1));
       
   396 bind_thm ("Spy_not_see_PMS", result() RSN (2, rev_mp));
   486 bind_thm ("Spy_not_see_PMS", result() RSN (2, rev_mp));
   397 
   487 
   398 
   488 
   399 
   489 
   400 goal thy "!!evs. [| Nonce (PRF (PMS,NA,NB)) : parts (sees Spy evs);  \
       
   401 \                   evs : tls |]  \
       
   402 \                ==> Nonce PMS : parts (sees Spy evs)";
       
   403 by (etac rev_mp 1);
       
   404 by (parts_induct_tac 1);
       
   405 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees])));
       
   406 by (Fake_parts_insert_tac 1);
       
   407 (*Client key exchange*)
       
   408 by (Blast_tac 4);
       
   409 (*Server Hello: by freshness*)
       
   410 by (blast_tac (!claset addSEs sees_Spy_partsEs) 3);
       
   411 (*Client Hello: trivial*)
       
   412 by (Blast_tac 2);
       
   413 (*SpyKeys*)
       
   414 by (blast_tac (!claset addSEs sees_Spy_partsEs) 1);
       
   415 qed "MS_imp_PMS";
       
   416 AddSDs [MS_imp_PMS];
       
   417 
   490 
   418 
   491 
   419 (*If A sends ClientCertKeyEx to an honest B, then the MASTER SECRET
   492 (*If A sends ClientCertKeyEx to an honest B, then the MASTER SECRET
   420   will stay secret.*)
   493   will stay secret.*)
   421 goal thy
   494 goal thy
   422  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]           \
   495  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]           \
   423 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   496 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs  -->   \
   424 \            Nonce (PRF(PMS,NA,NB)) ~: analz (sees Spy evs)";
   497 \            Nonce (PRF(PMS,NA,NB)) ~: analz (sees Spy evs)";
   425 by (analz_induct_tac 1);   (*47 seconds???*)
   498 by (analz_induct_tac 1);   (*35 seconds*)
       
   499 (*ClientAccepts and ServerAccepts: because PMS was already visible*)
       
   500 by (REPEAT (blast_tac (!claset addDs [Spy_not_see_PMS, 
       
   501 				      Says_imp_sees_Spy RS analz.Inj,
       
   502 				      Notes_imp_sees_Spy RS analz.Inj]) 6));
   426 (*ClientHello*)
   503 (*ClientHello*)
   427 by (Blast_tac 3);
   504 by (Blast_tac 3);
   428 (*SpyKeys: by secrecy of the PMS, Spy cannot make the MS*)
   505 (*SpyKeys: by secrecy of the PMS, Spy cannot make the MS*)
   429 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   506 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2);
   430 by (blast_tac (!claset addSDs [Spy_not_see_PMS, 
   507 by (blast_tac (!claset addSDs [Spy_not_see_PMS, 
   431 			       Says_imp_sees_Spy RS analz.Inj]) 2);
   508 			       Says_imp_sees_Spy RS analz.Inj]) 2);
   432 (*Fake*)
   509 (*Fake*)
   433 by (spy_analz_tac 1);
   510 by (spy_analz_tac 1);
   434 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
   511 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*)
   435 by (REPEAT (blast_tac (!claset addSEs partsEs
   512 by (REPEAT (blast_tac (!claset addSEs partsEs
   436 			       addDs  [MS_imp_PMS,
   513 			       addDs  [Notes_Crypt_parts_sees,
   437 				       Notes_Crypt_parts_sees,
       
   438 				       impOfSubs analz_subset_parts,
   514 				       impOfSubs analz_subset_parts,
   439 				       Says_imp_sees_Spy RS analz.Inj]) 1));
   515 				       Says_imp_sees_Spy RS analz.Inj]) 1));
   440 bind_thm ("Spy_not_see_MS", result() RSN (2, rev_mp));
   516 bind_thm ("Spy_not_see_MS", result() RSN (2, rev_mp));
   441 
       
   442 
       
   443 
       
   444 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***)
       
   445 
       
   446 (** First, some lemmas about those write keys.  The proofs for serverK are 
       
   447     nearly identical to those for clientK. **)
       
   448 
       
   449 (*Lemma: those write keys are never sent if M (MASTER SECRET) is secure.  
       
   450   Converse doesn't hold; betraying M doesn't force the keys to be sent!*)
       
   451 
       
   452 goal thy 
       
   453  "!!evs. [| Nonce M ~: analz (sees Spy evs);  evs : tls |]   \
       
   454 \        ==> Key (clientK(NA,NB,M)) ~: parts (sees Spy evs)";
       
   455 by (etac rev_mp 1);
       
   456 by (analz_induct_tac 1);
       
   457 (*SpyKeys*)
       
   458 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
       
   459 by (blast_tac (!claset addDs [Says_imp_sees_Spy RS analz.Inj]) 3);
       
   460 (*Fake*) 
       
   461 by (spy_analz_tac 2);
       
   462 (*Base*)
       
   463 by (Blast_tac 1);
       
   464 qed "clientK_notin_parts";
       
   465 bind_thm ("clientK_in_partsE", clientK_notin_parts RSN (2, rev_notE));
       
   466 Addsimps [clientK_notin_parts];
       
   467 AddSEs [clientK_in_partsE, 
       
   468 	impOfSubs analz_subset_parts RS clientK_in_partsE];
       
   469 
       
   470 goal thy 
       
   471  "!!evs. [| Nonce M ~: analz (sees Spy evs);  evs : tls |]   \
       
   472 \        ==> Key (serverK(NA,NB,M)) ~: parts (sees Spy evs)";
       
   473 by (etac rev_mp 1);
       
   474 by (analz_induct_tac 1);
       
   475 (*SpyKeys*)
       
   476 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3);
       
   477 by (blast_tac (!claset addDs [Says_imp_sees_Spy RS analz.Inj]) 3);
       
   478 (*Fake*) 
       
   479 by (spy_analz_tac 2);
       
   480 (*Base*)
       
   481 by (Blast_tac 1);
       
   482 qed "serverK_notin_parts";
       
   483 bind_thm ("serverK_in_partsE", serverK_notin_parts RSN (2, rev_notE));
       
   484 Addsimps [serverK_notin_parts];
       
   485 AddSEs [serverK_in_partsE, 
       
   486 	impOfSubs analz_subset_parts RS serverK_in_partsE];
       
   487 
       
   488 
       
   489 (*Lemma: those write keys are never used if PMS is fresh.  
       
   490   Nonces don't have to agree, allowing session resumption.
       
   491   Converse doesn't hold; revealing PMS doesn't force the keys to be sent.
       
   492   They are NOT suitable as safe elim rules.*)
       
   493 
       
   494 goal thy 
       
   495  "!!evs. [| Nonce PMS ~: used evs;  evs : tls |]                           \
       
   496 \  ==> Crypt (clientK(Na, Nb, PRF(PMS,NA,NB))) Y ~: parts (sees Spy evs)";
       
   497 by (etac rev_mp 1);
       
   498 by (analz_induct_tac 1);
       
   499 (*ClientFinished: since M is fresh, a different instance of clientK was used.*)
       
   500 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   501                        addSEs sees_Spy_partsEs) 3);
       
   502 by (Fake_parts_insert_tac 2);
       
   503 (*Base*)
       
   504 by (Blast_tac 1);
       
   505 qed "Crypt_clientK_notin_parts";
       
   506 Addsimps [Crypt_clientK_notin_parts];
       
   507 AddEs [Crypt_clientK_notin_parts RSN (2, rev_notE)];
       
   508 
       
   509 goal thy 
       
   510  "!!evs. [| Nonce PMS ~: used evs;  evs : tls |]                           \
       
   511 \  ==> Crypt (serverK(Na, Nb, PRF(PMS,NA,NB))) Y ~: parts (sees Spy evs)";
       
   512 by (etac rev_mp 1);
       
   513 by (analz_induct_tac 1);
       
   514 (*ServerFinished: since M is fresh, a different instance of serverK was used.*)
       
   515 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees]
       
   516                                addSEs sees_Spy_partsEs) 3);
       
   517 by (Fake_parts_insert_tac 2);
       
   518 (*Base*)
       
   519 by (Blast_tac 1);
       
   520 qed "Crypt_serverK_notin_parts";
       
   521 
       
   522 Addsimps [Crypt_serverK_notin_parts];
       
   523 AddEs [Crypt_serverK_notin_parts RSN (2, rev_notE)];
       
   524 
       
   525 
       
   526 (*NEEDED??*)
       
   527 goal thy
       
   528  "!!evs. [| Says A B {|certA, Crypt KB (Nonce M)|} : set evs;   \
       
   529 \           A ~= Spy;  evs : tls |] ==> KB = pubK B";
       
   530 be rev_mp 1;
       
   531 by (analz_induct_tac 1);
       
   532 qed "A_Crypt_pubB";
       
   533 
       
   534 
       
   535 (*** Unicity results for PMS, the pre-master-secret ***)
       
   536 
       
   537 (*PMS determines B.  Proof borrowed from NS_Public/unique_NA and from Yahalom*)
       
   538 goal thy 
       
   539  "!!evs. [| Nonce PMS ~: analz (sees Spy evs);  evs : tls |]   \
       
   540 \        ==> EX B'. ALL B.   \
       
   541 \              Crypt (pubK B) (Nonce PMS) : parts (sees Spy evs) --> B=B'";
       
   542 by (etac rev_mp 1);
       
   543 by (parts_induct_tac 1);
       
   544 by (Fake_parts_insert_tac 1);
       
   545 (*ClientCertKeyEx*)
       
   546 by (ClientCertKeyEx_tac 1);
       
   547 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1);
       
   548 by (expand_case_tac "PMS = ?y" 1 THEN
       
   549     blast_tac (!claset addSEs partsEs) 1);
       
   550 val lemma = result();
       
   551 
       
   552 goal thy 
       
   553  "!!evs. [| Crypt(pubK B)  (Nonce PMS) : parts (sees Spy evs); \
       
   554 \           Crypt(pubK B') (Nonce PMS) : parts (sees Spy evs); \
       
   555 \           Nonce PMS ~: analz (sees Spy evs);                 \
       
   556 \           evs : tls |]                                          \
       
   557 \        ==> B=B'";
       
   558 by (prove_unique_tac lemma 1);
       
   559 qed "unique_PMS";
       
   560 
       
   561 
       
   562 (*In A's note to herself, PMS determines A and B.*)
       
   563 goal thy 
       
   564  "!!evs. [| Nonce PMS ~: analz (sees Spy evs);  evs : tls |]            \
       
   565 \ ==> EX A' B'. ALL A B.                                                   \
       
   566 \        Notes A {|Agent B, Nonce PMS|} : set evs --> A=A' & B=B'";
       
   567 by (etac rev_mp 1);
       
   568 by (parts_induct_tac 1);
       
   569 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1);
       
   570 (*ClientCertKeyEx: if PMS is fresh, then it can't appear in Notes A X.*)
       
   571 by (expand_case_tac "PMS = ?y" 1 THEN
       
   572     blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1);
       
   573 val lemma = result();
       
   574 
       
   575 goal thy 
       
   576  "!!evs. [| Notes A  {|Agent B,  Nonce PMS|} : set evs;  \
       
   577 \           Notes A' {|Agent B', Nonce PMS|} : set evs;  \
       
   578 \           Nonce PMS ~: analz (sees Spy evs);      \
       
   579 \           evs : tls |]                               \
       
   580 \        ==> A=A' & B=B'";
       
   581 by (prove_unique_tac lemma 1);
       
   582 qed "Notes_unique_PMS";
       
   583 
       
   584 
   517 
   585 
   518 
   586 (*** Protocol goals: if A receives SERVER FINISHED, then B is present 
   519 (*** Protocol goals: if A receives SERVER FINISHED, then B is present 
   587      and has used the quoted values XA, XB, etc.  Note that it is up to A
   520      and has used the quoted values XA, XB, etc.  Note that it is up to A
   588      to compare XA with what she originally sent.
   521      to compare XA with what she originally sent.
   597 \           M = PRF(PMS,NA,NB);                           \
   530 \           M = PRF(PMS,NA,NB);                           \
   598 \           evs : tls;  A ~: lost;  B ~: lost |]          \
   531 \           evs : tls;  A ~: lost;  B ~: lost |]          \
   599 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \
   532 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \
   600 \        X : parts (sees Spy evs) --> Says B A X : set evs";
   533 \        X : parts (sees Spy evs) --> Says B A X : set evs";
   601 by (hyp_subst_tac 1);
   534 by (hyp_subst_tac 1);
   602 by (analz_induct_tac 1);
   535 by (analz_induct_tac 1);	(*16 seconds*)
       
   536 (*ClientCertKeyEx*)
       
   537 by (Blast_tac 2);
   603 (*Fake: the Spy doesn't have the critical session key!*)
   538 (*Fake: the Spy doesn't have the critical session key!*)
   604 by (REPEAT (rtac impI 1));
   539 by (REPEAT (rtac impI 1));
   605 by (subgoal_tac 
   540 by (subgoal_tac "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(sees Spy evsa)" 1);
   606     "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1);
       
   607 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   541 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   608 				     not_parts_not_analz]) 2);
   542 				     not_parts_not_analz]) 2);
   609 by (Fake_parts_insert_tac 1);
   543 by (Fake_parts_insert_tac 1);
   610 qed_spec_mp "TrustServerFinished";
   544 qed_spec_mp "TrustServerFinished";
   611 
   545 
   620 \           M = PRF(PMS,NA,NB) |]            \
   554 \           M = PRF(PMS,NA,NB) |]            \
   621 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs -->              \
   555 \        ==> Notes A {|Agent B, Nonce PMS|} : set evs -->              \
   622 \            Crypt (serverK(Na,Nb,M)) Y : parts (sees Spy evs)  -->  \
   556 \            Crypt (serverK(Na,Nb,M)) Y : parts (sees Spy evs)  -->  \
   623 \            (EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs)";
   557 \            (EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs)";
   624 by (hyp_subst_tac 1);
   558 by (hyp_subst_tac 1);
   625 by (analz_induct_tac 1);
   559 by (analz_induct_tac 1);	(*12 seconds*)
   626 by (REPEAT_FIRST (rtac impI));
   560 by (REPEAT_FIRST (rtac impI));
       
   561 (*ClientCertKeyEx*)
       
   562 by (Blast_tac 2);
   627 (*Fake: the Spy doesn't have the critical session key!*)
   563 (*Fake: the Spy doesn't have the critical session key!*)
   628 by (subgoal_tac 
   564 by (subgoal_tac "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(sees Spy evsa)" 1);
   629     "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1);
       
   630 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   565 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   631 				     not_parts_not_analz]) 2);
   566 				     not_parts_not_analz]) 2);
   632 by (Fake_parts_insert_tac 1);
   567 by (Fake_parts_insert_tac 1);
   633 (*ServerFinished.  If the message is old then apply induction hypothesis...*)
   568 (*ServerFinished.  If the message is old then apply induction hypothesis...*)
   634 by (rtac conjI 1 THEN Blast_tac 2);
   569 by (rtac conjI 1 THEN Blast_tac 2);
   635 (*...otherwise delete induction hyp and use unicity of PMS.*)
   570 (*...otherwise delete induction hyp and use unicity of PMS.*)
   636 by (thin_tac "?PP-->?QQ" 1);
   571 by (thin_tac "?PP-->?QQ" 1);
   637 by (Step_tac 1);
   572 by (Step_tac 1);
   638 by (subgoal_tac "Nonce PMS ~: analz (sees Spy evsSF)" 1);
   573 by (subgoal_tac "Nonce PMS ~: analz(sees Spy evsSF)" 1);
   639 by (asm_simp_tac (!simpset addsimps [Spy_not_see_PMS]) 2);
   574 by (asm_simp_tac (!simpset addsimps [Spy_not_see_PMS]) 2);
   640 by (blast_tac (!claset addSEs [MPair_parts]
   575 by (blast_tac (!claset addSEs [MPair_parts]
   641 		       addDs  [Notes_Crypt_parts_sees,
   576 		       addDs  [Notes_Crypt_parts_sees,
   642 			       Says_imp_sees_Spy RS parts.Inj,
   577 			       Says_imp_sees_Spy RS parts.Inj,
   643 			       unique_PMS]) 1);
   578 			       unique_PMS]) 1);
   652 goal thy
   587 goal thy
   653  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]                         \
   588  "!!evs. [| evs : tls;  A ~: lost;  B ~: lost |]                         \
   654 \  ==> Notes A {|Agent B, Nonce PMS|} : set evs -->                  \
   589 \  ==> Notes A {|Agent B, Nonce PMS|} : set evs -->                  \
   655 \      Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y : parts (sees Spy evs) -->  \
   590 \      Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y : parts (sees Spy evs) -->  \
   656 \      Says A B (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs";
   591 \      Says A B (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs";
   657 by (analz_induct_tac 1);
   592 by (analz_induct_tac 1);	(*13 seconds*)
   658 by (REPEAT_FIRST (rtac impI));
   593 by (REPEAT_FIRST (rtac impI));
       
   594 (*ClientCertKeyEx*)
       
   595 by (Blast_tac 2);
   659 (*Fake: the Spy doesn't have the critical session key!*)
   596 (*Fake: the Spy doesn't have the critical session key!*)
   660 by (subgoal_tac 
   597 by (subgoal_tac "Key (clientK(Na,Nb,PRF(PMS,NA,NB))) ~: analz(sees Spy evsa)" 1);
   661     "Key (clientK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1);
       
   662 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   598 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, 
   663 				     not_parts_not_analz]) 2);
   599 				     not_parts_not_analz]) 2);
   664 by (Fake_parts_insert_tac 1);
   600 by (Fake_parts_insert_tac 1);
   665 (*ClientFinished.  If the message is old then apply induction hypothesis...*)
   601 (*ClientFinished.  If the message is old then apply induction hypothesis...*)
   666 by (step_tac (!claset delrules [conjI]) 1);
   602 by (step_tac (!claset delrules [conjI]) 1);