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. |