src/HOL/Auth/OtwayRees_Bad.ML
author paulson
Fri Jul 04 17:34:55 1997 +0200 (1997-07-04)
changeset 3500 0d8ad2f192d8
parent 3466 30791e5a69c4
child 3519 ab0a9fbed4c0
permissions -rw-r--r--
New constant "certificate"--just an abbreviation
     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 open OtwayRees_Bad;
    19 
    20 proof_timing:=true;
    21 HOL_quantifiers := false;
    22 
    23 (*Replacing the variable by a constant improves search speed by 50%!*)
    24 val Says_imp_sees_Spy' = 
    25     read_instantiate_sg (sign_of thy) [("lost","lost")] Says_imp_sees_Spy;
    26 
    27 (*A "possibility property": there are traces that reach the end*)
    28 goal thy 
    29  "!!A B. [| A ~= B; A ~= Server; B ~= Server |]   \
    30 \        ==> EX K. EX NA. EX evs: otway.          \
    31 \               Says B A {|Nonce NA, Crypt (shrK A) {|Nonce NA, Key K|}|} \
    32 \                 : set evs";
    33 by (REPEAT (resolve_tac [exI,bexI] 1));
    34 by (rtac (otway.Nil RS otway.OR1 RS otway.OR2 RS otway.OR3 RS otway.OR4) 2);
    35 by possibility_tac;
    36 result();
    37 
    38 
    39 (**** Inductive proofs about otway ****)
    40 
    41 (*Nobody sends themselves messages*)
    42 goal thy "!!evs. evs : otway ==> ALL A X. Says A A X ~: set evs";
    43 by (etac otway.induct 1);
    44 by (Auto_tac());
    45 qed_spec_mp "not_Says_to_self";
    46 Addsimps [not_Says_to_self];
    47 AddSEs   [not_Says_to_self RSN (2, rev_notE)];
    48 
    49 
    50 (** For reasoning about the encrypted portion of messages **)
    51 
    52 goal thy "!!evs. Says A' B {|N, Agent A, Agent B, X|} : set evs ==> \
    53 \                X : analz (sees lost Spy evs)";
    54 by (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS analz.Inj]) 1);
    55 qed "OR2_analz_sees_Spy";
    56 
    57 goal thy "!!evs. Says S' B {|N, X, Crypt (shrK B) X'|} : set evs ==> \
    58 \                X : analz (sees lost Spy evs)";
    59 by (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS analz.Inj]) 1);
    60 qed "OR4_analz_sees_Spy";
    61 
    62 goal thy "!!evs. Says Server B {|NA, X, Crypt K' {|NB,K|}|} : set evs \
    63 \                 ==> K : parts (sees lost Spy evs)";
    64 by (blast_tac (!claset addSEs sees_Spy_partsEs) 1);
    65 qed "Oops_parts_sees_Spy";
    66 
    67 (*OR2_analz... and OR4_analz... let us treat those cases using the same 
    68   argument as for the Fake case.  This is possible for most, but not all,
    69   proofs: Fake does not invent new nonces (as in OR2), and of course Fake
    70   messages originate from the Spy. *)
    71 
    72 bind_thm ("OR2_parts_sees_Spy",
    73           OR2_analz_sees_Spy RS (impOfSubs analz_subset_parts));
    74 bind_thm ("OR4_parts_sees_Spy",
    75           OR4_analz_sees_Spy RS (impOfSubs analz_subset_parts));
    76 
    77 (*For proving the easier theorems about X ~: parts (sees lost Spy evs) *)
    78 val parts_induct_tac = 
    79     etac otway.induct 1 THEN 
    80     forward_tac [OR2_parts_sees_Spy] 4 THEN 
    81     forward_tac [OR4_parts_sees_Spy] 6 THEN
    82     forward_tac [Oops_parts_sees_Spy] 7 THEN
    83     prove_simple_subgoals_tac 1;
    84 
    85 
    86 (** Theorems of the form X ~: parts (sees lost Spy evs) imply that NOBODY
    87     sends messages containing X! **)
    88 
    89 (*Spy never sees another agent's shared key! (unless it's lost at start)*)
    90 goal thy 
    91  "!!evs. evs : otway \
    92 \        ==> (Key (shrK A) : parts (sees lost Spy evs)) = (A : lost)";
    93 by parts_induct_tac;
    94 by (Fake_parts_insert_tac 1);
    95 by (Blast_tac 1);
    96 qed "Spy_see_shrK";
    97 Addsimps [Spy_see_shrK];
    98 
    99 goal thy 
   100  "!!evs. evs : otway \
   101 \        ==> (Key (shrK A) : analz (sees lost Spy evs)) = (A : lost)";
   102 by (auto_tac(!claset addDs [impOfSubs analz_subset_parts], !simpset));
   103 qed "Spy_analz_shrK";
   104 Addsimps [Spy_analz_shrK];
   105 
   106 goal thy  "!!A. [| Key (shrK A) : parts (sees lost Spy evs);       \
   107 \                  evs : otway |] ==> A:lost";
   108 by (blast_tac (!claset addDs [Spy_see_shrK]) 1);
   109 qed "Spy_see_shrK_D";
   110 
   111 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D);
   112 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D];
   113 
   114 
   115 (*Nobody can have used non-existent keys!*)
   116 goal thy "!!evs. evs : otway ==>          \
   117 \         Key K ~: used evs --> K ~: keysFor (parts (sees lost Spy evs))";
   118 by parts_induct_tac;
   119 (*Fake*)
   120 by (best_tac
   121       (!claset addIs [impOfSubs analz_subset_parts]
   122                addDs [impOfSubs (analz_subset_parts RS keysFor_mono),
   123                       impOfSubs (parts_insert_subset_Un RS keysFor_mono)]
   124                addss (!simpset)) 1);
   125 (*OR1-3*)
   126 by (ALLGOALS Blast_tac);
   127 qed_spec_mp "new_keys_not_used";
   128 
   129 bind_thm ("new_keys_not_analzd",
   130           [analz_subset_parts RS keysFor_mono,
   131            new_keys_not_used] MRS contra_subsetD);
   132 
   133 Addsimps [new_keys_not_used, new_keys_not_analzd];
   134 
   135 
   136 
   137 (*** Proofs involving analz ***)
   138 
   139 (*Describes the form of K and NA when the Server sends this message.  Also
   140   for Oops case.*)
   141 goal thy 
   142  "!!evs. [| Says Server B                                                 \
   143 \            {|NA, X, Crypt (shrK B) {|NB, Key K|}|} : set evs;           \
   144 \           evs : otway |]                                                \
   145 \     ==> K ~: range shrK & (EX i. NA = Nonce i) & (EX j. NB = Nonce j)";
   146 by (etac rev_mp 1);
   147 by (etac otway.induct 1);
   148 by (prove_simple_subgoals_tac 1);
   149 by (Blast_tac 1); 
   150 qed "Says_Server_message_form";
   151 
   152 
   153 (*For proofs involving analz.*)
   154 val analz_sees_tac = 
   155     dtac OR2_analz_sees_Spy 4 THEN 
   156     dtac OR4_analz_sees_Spy 6 THEN
   157     forward_tac [Says_Server_message_form] 7 THEN assume_tac 7 THEN 
   158     REPEAT ((eresolve_tac [exE, conjE] ORELSE' hyp_subst_tac) 7);
   159 
   160 
   161 (****
   162  The following is to prove theorems of the form
   163 
   164   Key K : analz (insert (Key KAB) (sees lost Spy evs)) ==>
   165   Key K : analz (sees lost Spy evs)
   166 
   167  A more general formula must be proved inductively.
   168 ****)
   169 
   170 
   171 (** Session keys are not used to encrypt other session keys **)
   172 
   173 (*The equality makes the induction hypothesis easier to apply*)
   174 goal thy  
   175  "!!evs. evs : otway ==>                                         \
   176 \  ALL K KK. KK <= Compl (range shrK) -->                        \
   177 \            (Key K : analz (Key``KK Un (sees lost Spy evs))) =  \
   178 \            (K : KK | Key K : analz (sees lost Spy evs))";
   179 by (etac otway.induct 1);
   180 by analz_sees_tac;
   181 by (REPEAT_FIRST (resolve_tac [allI, impI]));
   182 by (REPEAT_FIRST (rtac analz_image_freshK_lemma ));
   183 by (ALLGOALS (asm_simp_tac analz_image_freshK_ss));
   184 (*Fake*) 
   185 by (spy_analz_tac 2);
   186 (*Base*)
   187 by (Blast_tac 1);
   188 qed_spec_mp "analz_image_freshK";
   189 
   190 
   191 goal thy
   192  "!!evs. [| evs : otway;  KAB ~: range shrK |] ==>              \
   193 \        Key K : analz (insert (Key KAB) (sees lost Spy evs)) = \
   194 \        (K = KAB | Key K : analz (sees lost Spy evs))";
   195 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1);
   196 qed "analz_insert_freshK";
   197 
   198 
   199 (*** The Key K uniquely identifies the Server's  message. **)
   200 
   201 goal thy 
   202  "!!evs. evs : otway ==>                                                  \
   203 \   EX B' NA' NB' X'. ALL B NA NB X.                                      \
   204 \     Says Server B {|NA, X, Crypt (shrK B) {|NB, K|}|} : set evs -->     \
   205 \     B=B' & NA=NA' & NB=NB' & X=X'";
   206 by (etac otway.induct 1);
   207 by (ALLGOALS (asm_simp_tac (!simpset addsimps [all_conj_distrib])));
   208 by (Step_tac 1);
   209 (*Remaining cases: OR3 and OR4*)
   210 by (ex_strip_tac 2);
   211 by (Blast_tac 2);
   212 by (expand_case_tac "K = ?y" 1);
   213 by (REPEAT (ares_tac [refl,exI,impI,conjI] 2));
   214 (*...we assume X is a recent message, and handle this case by contradiction*)
   215 by (blast_tac (!claset addSEs sees_Spy_partsEs
   216                       delrules [conjI]    (*no split-up to 4 subgoals*)) 1);
   217 val lemma = result();
   218 
   219 goal thy 
   220  "!!evs. [| Says Server B {|NA, X, Crypt (shrK B) {|NB, K|}|}   : set evs; \ 
   221 \           Says Server B' {|NA',X',Crypt (shrK B') {|NB',K|}|} : set evs; \
   222 \           evs : otway |] ==> X=X' & B=B' & NA=NA' & NB=NB'";
   223 by (prove_unique_tac lemma 1);
   224 qed "unique_session_keys";
   225 
   226 
   227 (*Crucial security property, but not itself enough to guarantee correctness!*)
   228 goal thy 
   229  "!!evs. [| A ~: lost;  B ~: lost;  evs : otway |]                    \
   230 \        ==> Says Server B                                            \
   231 \              {|NA, Crypt (shrK A) {|NA, Key K|},                    \
   232 \                Crypt (shrK B) {|NB, Key K|}|} : set evs -->         \
   233 \            Says B Spy {|NA, NB, Key K|} ~: set evs -->              \
   234 \            Key K ~: analz (sees lost Spy evs)";
   235 by (etac otway.induct 1);
   236 by analz_sees_tac;
   237 by (ALLGOALS
   238     (asm_simp_tac (!simpset addcongs [conj_cong] 
   239                             addsimps [analz_insert_eq, not_parts_not_analz, 
   240 				      analz_insert_freshK]
   241                             setloop split_tac [expand_if])));
   242 (*Oops*)
   243 by (blast_tac (!claset addSDs [unique_session_keys]) 4);
   244 (*OR4*) 
   245 by (Blast_tac 3);
   246 (*OR3*)
   247 by (blast_tac (!claset addSEs sees_Spy_partsEs
   248                        addIs [impOfSubs analz_subset_parts]) 2);
   249 (*Fake*) 
   250 by (spy_analz_tac 1);
   251 val lemma = result() RS mp RS mp RSN(2,rev_notE);
   252 
   253 goal thy 
   254  "!!evs. [| Says Server B                                         \
   255 \            {|NA, Crypt (shrK A) {|NA, Key K|},                  \
   256 \                  Crypt (shrK B) {|NB, Key K|}|} : set evs;      \
   257 \           Says B Spy {|NA, NB, Key K|} ~: set evs;              \
   258 \           A ~: lost;  B ~: lost;  evs : otway |]                \
   259 \        ==> Key K ~: analz (sees lost Spy evs)";
   260 by (forward_tac [Says_Server_message_form] 1 THEN assume_tac 1);
   261 by (blast_tac (!claset addSEs [lemma]) 1);
   262 qed "Spy_not_see_encrypted_key";
   263 
   264 
   265 (*** Attempting to prove stronger properties ***)
   266 
   267 (*Only OR1 can have caused such a part of a message to appear.
   268   I'm not sure why A ~= B premise is needed: OtwayRees.ML doesn't need it.
   269   Perhaps it's because OR2 has two similar-looking encrypted messages in
   270         this version.*)
   271 goal thy 
   272  "!!evs. [| A ~: lost;  A ~= B;  evs : otway |]                \
   273 \        ==> Crypt (shrK A) {|NA, Agent A, Agent B|}           \
   274 \             : parts (sees lost Spy evs) -->                  \
   275 \            Says A B {|NA, Agent A, Agent B,                  \
   276 \                       Crypt (shrK A) {|NA, Agent A, Agent B|}|}  : set evs";
   277 by parts_induct_tac;
   278 by (Fake_parts_insert_tac 1);
   279 by (Blast_tac 1);
   280 qed_spec_mp "Crypt_imp_OR1";
   281 
   282 
   283 (*Crucial property: If the encrypted message appears, and A has used NA
   284   to start a run, then it originated with the Server!*)
   285 (*Only it is FALSE.  Somebody could make a fake message to Server
   286           substituting some other nonce NA' for NB.*)
   287 goal thy 
   288  "!!evs. [| A ~: lost;  A ~= Spy;  evs : otway |]                         \
   289 \        ==> Crypt (shrK A) {|NA, Key K|} : parts (sees lost Spy evs) --> \
   290 \            Says A B {|NA, Agent A, Agent B,                      \
   291 \                       Crypt (shrK A) {|NA, Agent A, Agent B|}|}  \
   292 \             : set evs -->                                    \
   293 \            (EX B NB. Says Server B                           \
   294 \                 {|NA,                                        \
   295 \                   Crypt (shrK A) {|NA, Key K|},              \
   296 \                   Crypt (shrK B) {|NB, Key K|}|}  : set evs)";
   297 by parts_induct_tac;
   298 by (Fake_parts_insert_tac 1);
   299 (*OR1: it cannot be a new Nonce, contradiction.*)
   300 by (blast_tac (!claset addSIs [parts_insertI]
   301                       addSEs sees_Spy_partsEs) 1);
   302 (*OR4*)
   303 by (REPEAT (Safe_step_tac 2));
   304 by (REPEAT (blast_tac (!claset addSDs [parts_cut]) 3));
   305 by (blast_tac (!claset addSIs [Crypt_imp_OR1]
   306                        addEs  sees_Spy_partsEs) 2);
   307 (*OR3*)  (** LEVEL 5 **)
   308 by (ALLGOALS (asm_simp_tac (!simpset addsimps [ex_disj_distrib])));
   309 by (step_tac (!claset delrules [disjCI, impCE]) 1);
   310 (*The hypotheses at this point suggest an attack in which nonce NA is used
   311   in two different roles:
   312           Says B' Server
   313            {|Nonce NAa, Agent Aa, Agent A,
   314              Crypt (shrK Aa) {|Nonce NAa, Agent Aa, Agent A|}, Nonce NA,
   315              Crypt (shrK A) {|Nonce NAa, Agent Aa, Agent A|}|}
   316           : set evsa;
   317           Says A B
   318            {|Nonce NA, Agent A, Agent B,
   319              Crypt (shrK A) {|Nonce NA, Agent A, Agent B|}|}
   320           : set evsa 
   321 *)
   322 writeln "GIVE UP! on NA_Crypt_imp_Server_msg";
   323 
   324 
   325 (*Thus the key property A_can_trust probably fails too.*)