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