src/HOL/Auth/OtwayRees_Bad.ML
author paulson
Thu Sep 23 13:06:31 1999 +0200 (1999-09-23)
changeset 7584 5be4bb8e4e3f
parent 7499 23e090051cb8
child 10833 c0844a30ea4e
permissions -rw-r--r--
tidied; added lemma restrict_to_left
     1 (*  Title:      HOL/Auth/OtwayRees_Bad
     2     ID:         $Id$
     3     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     4     Copyright   1996  University of Cambridge
     5 
     6 Inductive relation "otway" for the Otway-Rees protocol.
     7 
     8 The FAULTY version omitting encryption of Nonce NB, as suggested on page 247 of
     9   Burrows, Abadi and Needham.  A Logic of Authentication.
    10   Proc. Royal Soc. 426 (1989)
    11 
    12 This file illustrates the consequences of such errors.  We can still prove
    13 impressive-looking properties such as Spy_not_see_encrypted_key, yet the
    14 protocol is open to a middleperson attack.  Attempting to prove some key lemmas
    15 indicates the possibility of this attack.
    16 *)
    17 
    18 AddEs knows_Spy_partsEs;
    19 AddDs [impOfSubs analz_subset_parts];
    20 AddDs [impOfSubs Fake_parts_insert];
    21 
    22 
    23 (*A "possibility property": there are traces that reach the end*)
    24 Goal "[| A ~= B; B ~= Server |]   \
    25 \     ==> EX K. EX NA. EX evs: otway.          \
    26 \           Says B A {|Nonce NA, Crypt (shrK A) {|Nonce NA, Key K|}|} \
    27 \             : set evs";
    28 by (REPEAT (resolve_tac [exI,bexI] 1));
    29 by (rtac (otway.Nil RS 
    30           otway.OR1 RS otway.Reception RS
    31           otway.OR2 RS otway.Reception RS 
    32           otway.OR3 RS otway.Reception RS otway.OR4) 2);
    33 by possibility_tac;
    34 result();
    35 
    36 Goal "[| Gets B X : set evs; evs : otway |] ==> EX A. Says A B X : set evs";
    37 by (etac rev_mp 1);
    38 by (etac otway.induct 1);
    39 by Auto_tac;
    40 qed"Gets_imp_Says";
    41 
    42 (*Must be proved separately for each protocol*)
    43 Goal "[| Gets B X : set evs; evs : otway |]  ==> X : knows Spy evs";
    44 by (blast_tac (claset() addSDs [Gets_imp_Says, Says_imp_knows_Spy]) 1);
    45 qed"Gets_imp_knows_Spy";
    46 AddDs [Gets_imp_knows_Spy RS parts.Inj];
    47 
    48 
    49 (**** Inductive proofs about otway ****)
    50 
    51 
    52 (** For reasoning about the encrypted portion of messages **)
    53 
    54 Goal "[| Gets B {|N, Agent A, Agent B, X|} : set evs;  evs : otway |] \
    55 \     ==> X : analz (knows Spy evs)";
    56 by (blast_tac (claset() addSDs [Gets_imp_knows_Spy RS analz.Inj]) 1);
    57 qed "OR2_analz_knows_Spy";
    58 
    59 Goal "[| Gets B {|N, X, Crypt (shrK B) X'|} : set evs;  evs : otway |] \
    60 \     ==> X : analz (knows Spy evs)";
    61 by (blast_tac (claset() addSDs [Gets_imp_knows_Spy RS analz.Inj]) 1);
    62 qed "OR4_analz_knows_Spy";
    63 
    64 Goal "Says Server B {|NA, X, Crypt K' {|NB,K|}|} : set evs \
    65 \     ==> K : parts (knows Spy evs)";
    66 by (Blast_tac 1);
    67 qed "Oops_parts_knows_Spy";
    68 
    69 bind_thm ("OR2_parts_knows_Spy",
    70           OR2_analz_knows_Spy RS (impOfSubs analz_subset_parts));
    71 bind_thm ("OR4_parts_knows_Spy",
    72           OR4_analz_knows_Spy RS (impOfSubs analz_subset_parts));
    73 
    74 (*For proving the easier theorems about X ~: parts (knows Spy evs).*)
    75 fun parts_induct_tac i = 
    76     etac otway.induct i			THEN 
    77     ftac Oops_parts_knows_Spy (i+7) THEN
    78     ftac OR4_parts_knows_Spy (i+6) THEN
    79     ftac OR2_parts_knows_Spy (i+4) THEN 
    80     prove_simple_subgoals_tac  i;
    81 
    82 
    83 (** Theorems of the form X ~: parts (knows Spy evs) imply that NOBODY
    84     sends messages containing X! **)
    85 
    86 (*Spy never sees a good agent's shared key!*)
    87 Goal "evs : otway ==> (Key (shrK A) : parts (knows Spy evs)) = (A : bad)";
    88 by (parts_induct_tac 1);
    89 by (ALLGOALS Blast_tac);
    90 qed "Spy_see_shrK";
    91 Addsimps [Spy_see_shrK];
    92 
    93 Goal "evs : otway ==> (Key (shrK A) : analz (knows Spy evs)) = (A : bad)";
    94 by (auto_tac(claset() addDs [impOfSubs analz_subset_parts], simpset()));
    95 qed "Spy_analz_shrK";
    96 Addsimps [Spy_analz_shrK];
    97 
    98 AddSDs [Spy_see_shrK RSN (2, rev_iffD1), 
    99 	Spy_analz_shrK RSN (2, rev_iffD1)];
   100 
   101 
   102 (*Nobody can have used non-existent keys!*)
   103 Goal "evs : otway ==> Key K ~: used evs --> K ~: keysFor (parts (knows Spy evs))";
   104 by (parts_induct_tac 1);
   105 (*Fake*)
   106 by (blast_tac (claset() addSDs [keysFor_parts_insert]) 1);
   107 (*OR2, OR3*)
   108 by (ALLGOALS Blast_tac);
   109 qed_spec_mp "new_keys_not_used";
   110 
   111 bind_thm ("new_keys_not_analzd",
   112           [analz_subset_parts RS keysFor_mono,
   113            new_keys_not_used] MRS contra_subsetD);
   114 
   115 Addsimps [new_keys_not_used, new_keys_not_analzd];
   116 
   117 
   118 
   119 (*** Proofs involving analz ***)
   120 
   121 (*Describes the form of K and NA when the Server sends this message.  Also
   122   for Oops case.*)
   123 Goal "[| Says Server B {|NA, X, Crypt (shrK B) {|NB, Key K|}|} : set evs; \
   124 \        evs : otway |]                                           \
   125 \  ==> K ~: range shrK & (EX i. NA = Nonce i) & (EX j. NB = Nonce j)";
   126 by (etac rev_mp 1);
   127 by (etac otway.induct 1);
   128 by (ALLGOALS Simp_tac);
   129 by (ALLGOALS Blast_tac);
   130 qed "Says_Server_message_form";
   131 
   132 
   133 (*For proofs involving analz.*)
   134 val analz_knows_Spy_tac = 
   135     dtac OR2_analz_knows_Spy 5 THEN assume_tac 5 THEN 
   136     dtac OR4_analz_knows_Spy 7 THEN assume_tac 7 THEN
   137     ftac Says_Server_message_form 8 THEN assume_tac 8 THEN
   138     REPEAT ((eresolve_tac [exE, conjE] ORELSE' hyp_subst_tac) 8);
   139 
   140 
   141 (****
   142  The following is to prove theorems of the form
   143 
   144   Key K : analz (insert (Key KAB) (knows Spy evs)) ==>
   145   Key K : analz (knows Spy evs)
   146 
   147  A more general formula must be proved inductively.
   148 ****)
   149 
   150 
   151 (** Session keys are not used to encrypt other session keys **)
   152 
   153 (*The equality makes the induction hypothesis easier to apply*)
   154 Goal "evs : otway ==>                                 \
   155 \  ALL K KK. KK <= - (range shrK) -->                 \
   156 \         (Key K : analz (Key``KK Un (knows Spy evs))) =  \
   157 \         (K : KK | Key K : analz (knows Spy evs))";
   158 by (etac otway.induct 1);
   159 by analz_knows_Spy_tac;
   160 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   161 by (REPEAT_FIRST (rtac analz_image_freshK_lemma ));
   162 by (ALLGOALS (asm_simp_tac analz_image_freshK_ss));
   163 (*Fake*) 
   164 by (spy_analz_tac 1);
   165 qed_spec_mp "analz_image_freshK";
   166 
   167 
   168 Goal "[| evs : otway;  KAB ~: range shrK |] ==>       \
   169 \     Key K : analz (insert (Key KAB) (knows Spy evs)) =  \
   170 \     (K = KAB | Key K : analz (knows Spy evs))";
   171 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1);
   172 qed "analz_insert_freshK";
   173 
   174 
   175 (*** The Key K uniquely identifies the Server's  message. **)
   176 
   177 Goal "evs : otway ==>                                                  \
   178 \     EX B' NA' NB' X'. ALL B NA NB X.                                    \
   179 \     Says Server B {|NA, X, Crypt (shrK B) {|NB, K|}|} : set evs -->     \
   180 \     B=B' & NA=NA' & NB=NB' & X=X'";
   181 by (etac otway.induct 1);
   182 by (ALLGOALS (asm_simp_tac (simpset() addsimps [all_conj_distrib])));
   183 by (ALLGOALS Clarify_tac);
   184 (*Remaining cases: OR3 and OR4*)
   185 by (ex_strip_tac 2);
   186 by (Best_tac 2);	(*Blast_tac's too slow (in reconstruction)*)
   187 by (expand_case_tac "K = ?y" 1);
   188 by (REPEAT (ares_tac [refl,exI,impI,conjI] 2));
   189 (*...we assume X is a recent message, and handle this case by contradiction*)
   190 by (blast_tac (claset() addSEs knows_Spy_partsEs) 1);
   191 val lemma = result();
   192 
   193 Goal "[| Says Server B {|NA, X, Crypt (shrK B) {|NB, K|}|}   : set evs; \ 
   194 \        Says Server B' {|NA',X',Crypt (shrK B') {|NB',K|}|} : set evs; \
   195 \        evs : otway |] ==> X=X' & B=B' & NA=NA' & NB=NB'";
   196 by (prove_unique_tac lemma 1);
   197 qed "unique_session_keys";
   198 
   199 
   200 (** Crucial secrecy property: Spy does not see the keys sent in msg OR3
   201     Does not in itself guarantee security: an attack could violate 
   202     the premises, e.g. by having A=Spy **)
   203 
   204 Goal "[| A ~: bad;  B ~: bad;  evs : otway |]                      \
   205 \     ==> Says Server B                                            \
   206 \           {|NA, Crypt (shrK A) {|NA, Key K|},                    \
   207 \             Crypt (shrK B) {|NB, Key K|}|} : set evs -->         \
   208 \         Notes Spy {|NA, NB, Key K|} ~: set evs -->               \
   209 \         Key K ~: analz (knows Spy evs)";
   210 by (etac otway.induct 1);
   211 by analz_knows_Spy_tac;
   212 by (ALLGOALS
   213     (asm_simp_tac (simpset() addcongs [conj_cong] 
   214                              addsimps [analz_insert_eq, analz_insert_freshK]
   215                                       @ pushes @ split_ifs)));
   216 (*Oops*)
   217 by (blast_tac (claset() addSDs [unique_session_keys]) 4);
   218 (*OR4*) 
   219 by (Blast_tac 3);
   220 (*OR3*)
   221 by (Blast_tac 2);
   222 (*Fake*) 
   223 by (spy_analz_tac 1);
   224 val lemma = result() RS mp RS mp RSN(2,rev_notE);
   225 
   226 Goal "[| Says Server B                                           \
   227 \         {|NA, Crypt (shrK A) {|NA, Key K|},                    \
   228 \               Crypt (shrK B) {|NB, Key K|}|} : set evs;        \
   229 \        Notes Spy {|NA, NB, Key K|} ~: set evs;                 \
   230 \        A ~: bad;  B ~: bad;  evs : otway |]                    \
   231 \     ==> Key K ~: analz (knows Spy evs)";
   232 by (ftac Says_Server_message_form 1 THEN assume_tac 1);
   233 by (blast_tac (claset() addSEs [lemma]) 1);
   234 qed "Spy_not_see_encrypted_key";
   235 
   236 
   237 (*** Attempting to prove stronger properties ***)
   238 
   239 (*Only OR1 can have caused such a part of a message to appear.
   240   The premise A ~= B prevents OR2's similar-looking cryptogram from being
   241   picked up.  Original Otway-Rees doesn't need it.*)
   242 Goal "[| A ~: bad;  A ~= B;  evs : otway |]                \
   243 \     ==> Crypt (shrK A) {|NA, Agent A, Agent B|} : parts (knows Spy evs) --> \
   244 \         Says A B {|NA, Agent A, Agent B,                  \
   245 \                    Crypt (shrK A) {|NA, Agent A, Agent B|}|}  : set evs";
   246 by (parts_induct_tac 1);
   247 by (ALLGOALS Blast_tac);
   248 qed_spec_mp "Crypt_imp_OR1";
   249 
   250 
   251 (*Crucial property: If the encrypted message appears, and A has used NA
   252   to start a run, then it originated with the Server!
   253   The premise A ~= B allows use of Crypt_imp_OR1*)
   254 (*Only it is FALSE.  Somebody could make a fake message to Server
   255           substituting some other nonce NA' for NB.*)
   256 Goal "[| A ~: bad;  A ~= B;  evs : otway |]                                \
   257 \     ==> Crypt (shrK A) {|NA, Key K|} : parts (knows Spy evs) -->    \
   258 \         Says A B {|NA, Agent A, Agent B,                        \
   259 \                    Crypt (shrK A) {|NA, Agent A, Agent B|}|}    \
   260 \          : set evs -->                                          \
   261 \         (EX B NB. Says Server B                                 \
   262 \              {|NA,                                              \
   263 \                Crypt (shrK A) {|NA, Key K|},                    \
   264 \                Crypt (shrK B) {|NB, Key K|}|}  : set evs)";
   265 by (parts_induct_tac 1);
   266 (*Fake*)
   267 by (Blast_tac 1);
   268 (*OR1: it cannot be a new Nonce, contradiction.*)
   269 by (Blast_tac 1);
   270 (*OR3 and OR4*)
   271 by (ALLGOALS (asm_simp_tac (simpset() addsimps [ex_disj_distrib])));
   272 by (ALLGOALS Clarify_tac);
   273 (*OR4*)
   274 by (blast_tac (claset() addSIs [Crypt_imp_OR1]) 2);
   275 (*OR3*)  (** LEVEL 5 **)
   276 (*The hypotheses at this point suggest an attack in which nonce NB is used
   277   in two different roles:
   278           Gets Server
   279            {|Nonce NA, Agent Aa, Agent A,
   280              Crypt (shrK Aa) {|Nonce NA, Agent Aa, Agent A|}, Nonce NB,
   281              Crypt (shrK A) {|Nonce NA, Agent Aa, Agent A|}|}
   282           : set evs3;
   283           Says A B
   284            {|Nonce NB, Agent A, Agent B,
   285              Crypt (shrK A) {|Nonce NB, Agent A, Agent B|}|}
   286           : set evs3;
   287 *)
   288 writeln "GIVE UP! on NA_Crypt_imp_Server_msg";
   289 
   290 
   291 (*Thus the key property A_can_trust probably fails too.*)