doc-src/TutorialI/Protocol/Message.thy
author Walther Neuper <neuper@ist.tugraz.at>
Thu, 12 Aug 2010 15:03:34 +0200
branchisac-from-Isabelle2009-2
changeset 37913 20e3616b2d9c
parent 35413 d8d7d1b785af
child 39528 7c69964c6d74
permissions -rw-r--r--
prepare reactivation of isac-update-Isa09-2
     1 (*  Title:      HOL/Auth/Message
     2     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     3     Copyright   1996  University of Cambridge
     4 
     5 Datatypes of agents and messages;
     6 Inductive relations "parts", "analz" and "synth"
     7 *)(*<*)
     8 
     9 header{*Theory of Agents and Messages for Security Protocols*}
    10 
    11 theory Message imports Main uses "../../antiquote_setup.ML" begin
    12 
    13 (*Needed occasionally with spy_analz_tac, e.g. in analz_insert_Key_newK*)
    14 lemma [simp] : "A \<union> (B \<union> A) = B \<union> A"
    15 by blast
    16 (*>*)
    17 
    18 section{* Agents and Messages *}
    19 
    20 text {*
    21 All protocol specifications refer to a syntactic theory of messages. 
    22 Datatype
    23 @{text agent} introduces the constant @{text Server} (a trusted central
    24 machine, needed for some protocols), an infinite population of
    25 friendly agents, and the~@{text Spy}:
    26 *}
    27 
    28 datatype agent = Server | Friend nat | Spy
    29 
    30 text {*
    31 Keys are just natural numbers.  Function @{text invKey} maps a public key to
    32 the matching private key, and vice versa:
    33 *}
    34 
    35 types key = nat
    36 consts invKey :: "key \<Rightarrow> key"
    37 (*<*)
    38 consts all_symmetric :: bool        --{*true if all keys are symmetric*}
    39 
    40 specification (invKey)
    41   invKey [simp]: "invKey (invKey K) = K"
    42   invKey_symmetric: "all_symmetric --> invKey = id"
    43     by (rule exI [of _ id], auto)
    44 
    45 
    46 text{*The inverse of a symmetric key is itself; that of a public key
    47       is the private key and vice versa*}
    48 
    49 definition symKeys :: "key set" where
    50   "symKeys == {K. invKey K = K}"
    51 (*>*)
    52 
    53 text {*
    54 Datatype
    55 @{text msg} introduces the message forms, which include agent names, nonces,
    56 keys, compound messages, and encryptions.  
    57 *}
    58 
    59 datatype
    60      msg = Agent  agent
    61          | Nonce  nat
    62          | Key    key
    63          | MPair  msg msg
    64          | Crypt  key msg
    65 
    66 text {*
    67 \noindent
    68 The notation $\comp{X\sb 1,\ldots X\sb{n-1},X\sb n}$
    69 abbreviates
    70 $\isa{MPair}\,X\sb 1\,\ldots\allowbreak(\isa{MPair}\,X\sb{n-1}\,X\sb n)$.
    71 
    72 Since datatype constructors are injective, we have the theorem
    73 @{thm [display,indent=0] msg.inject(5) [THEN iffD1, of K X K' X']}
    74 A ciphertext can be decrypted using only one key and
    75 can yield only one plaintext.  In the real world, decryption with the
    76 wrong key succeeds but yields garbage.  Our model of encryption is
    77 realistic if encryption adds some redundancy to the plaintext, such as a
    78 checksum, so that garbage can be detected.
    79 *}
    80 
    81 (*<*)
    82 text{*Concrete syntax: messages appear as {|A,B,NA|}, etc...*}
    83 syntax
    84   "_MTuple"      :: "['a, args] => 'a * 'b"       ("(2{|_,/ _|})")
    85 
    86 syntax (xsymbols)
    87   "_MTuple"      :: "['a, args] => 'a * 'b"       ("(2\<lbrace>_,/ _\<rbrace>)")
    88 
    89 translations
    90   "{|x, y, z|}"   == "{|x, {|y, z|}|}"
    91   "{|x, y|}"      == "CONST MPair x y"
    92 
    93 
    94 definition keysFor :: "msg set => key set" where
    95     --{*Keys useful to decrypt elements of a message set*}
    96   "keysFor H == invKey ` {K. \<exists>X. Crypt K X \<in> H}"
    97 
    98 
    99 subsubsection{*Inductive Definition of All Parts" of a Message*}
   100 
   101 inductive_set
   102   parts :: "msg set => msg set"
   103   for H :: "msg set"
   104   where
   105     Inj [intro]:               "X \<in> H ==> X \<in> parts H"
   106   | Fst:         "{|X,Y|}   \<in> parts H ==> X \<in> parts H"
   107   | Snd:         "{|X,Y|}   \<in> parts H ==> Y \<in> parts H"
   108   | Body:        "Crypt K X \<in> parts H ==> X \<in> parts H"
   109 
   110 
   111 text{*Monotonicity*}
   112 lemma parts_mono: "G \<subseteq> H ==> parts(G) \<subseteq> parts(H)"
   113 apply auto
   114 apply (erule parts.induct) 
   115 apply (blast dest: parts.Fst parts.Snd parts.Body)+
   116 done
   117 
   118 
   119 text{*Equations hold because constructors are injective.*}
   120 lemma Friend_image_eq [simp]: "(Friend x \<in> Friend`A) = (x:A)"
   121 by auto
   122 
   123 lemma Key_image_eq [simp]: "(Key x \<in> Key`A) = (x\<in>A)"
   124 by auto
   125 
   126 lemma Nonce_Key_image_eq [simp]: "(Nonce x \<notin> Key`A)"
   127 by auto
   128 
   129 
   130 subsubsection{*Inverse of keys *}
   131 
   132 lemma invKey_eq [simp]: "(invKey K = invKey K') = (K=K')"
   133 apply safe
   134 apply (drule_tac f = invKey in arg_cong, simp)
   135 done
   136 
   137 
   138 subsection{*keysFor operator*}
   139 
   140 lemma keysFor_empty [simp]: "keysFor {} = {}"
   141 by (unfold keysFor_def, blast)
   142 
   143 lemma keysFor_Un [simp]: "keysFor (H \<union> H') = keysFor H \<union> keysFor H'"
   144 by (unfold keysFor_def, blast)
   145 
   146 lemma keysFor_UN [simp]: "keysFor (\<Union>i\<in>A. H i) = (\<Union>i\<in>A. keysFor (H i))"
   147 by (unfold keysFor_def, blast)
   148 
   149 text{*Monotonicity*}
   150 lemma keysFor_mono: "G \<subseteq> H ==> keysFor(G) \<subseteq> keysFor(H)"
   151 by (unfold keysFor_def, blast)
   152 
   153 lemma keysFor_insert_Agent [simp]: "keysFor (insert (Agent A) H) = keysFor H"
   154 by (unfold keysFor_def, auto)
   155 
   156 lemma keysFor_insert_Nonce [simp]: "keysFor (insert (Nonce N) H) = keysFor H"
   157 by (unfold keysFor_def, auto)
   158 
   159 lemma keysFor_insert_Key [simp]: "keysFor (insert (Key K) H) = keysFor H"
   160 by (unfold keysFor_def, auto)
   161 
   162 lemma keysFor_insert_MPair [simp]: "keysFor (insert {|X,Y|} H) = keysFor H"
   163 by (unfold keysFor_def, auto)
   164 
   165 lemma keysFor_insert_Crypt [simp]: 
   166     "keysFor (insert (Crypt K X) H) = insert (invKey K) (keysFor H)"
   167 by (unfold keysFor_def, auto)
   168 
   169 lemma keysFor_image_Key [simp]: "keysFor (Key`E) = {}"
   170 by (unfold keysFor_def, auto)
   171 
   172 lemma Crypt_imp_invKey_keysFor: "Crypt K X \<in> H ==> invKey K \<in> keysFor H"
   173 by (unfold keysFor_def, blast)
   174 
   175 
   176 subsection{*Inductive relation "parts"*}
   177 
   178 lemma MPair_parts:
   179      "[| {|X,Y|} \<in> parts H;        
   180          [| X \<in> parts H; Y \<in> parts H |] ==> P |] ==> P"
   181 by (blast dest: parts.Fst parts.Snd) 
   182 
   183 declare MPair_parts [elim!]  parts.Body [dest!]
   184 text{*NB These two rules are UNSAFE in the formal sense, as they discard the
   185      compound message.  They work well on THIS FILE.  
   186   @{text MPair_parts} is left as SAFE because it speeds up proofs.
   187   The Crypt rule is normally kept UNSAFE to avoid breaking up certificates.*}
   188 
   189 lemma parts_increasing: "H \<subseteq> parts(H)"
   190 by blast
   191 
   192 lemmas parts_insertI = subset_insertI [THEN parts_mono, THEN subsetD, standard]
   193 
   194 lemma parts_empty [simp]: "parts{} = {}"
   195 apply safe
   196 apply (erule parts.induct, blast+)
   197 done
   198 
   199 lemma parts_emptyE [elim!]: "X\<in> parts{} ==> P"
   200 by simp
   201 
   202 text{*WARNING: loops if H = {Y}, therefore must not be repeated!*}
   203 lemma parts_singleton: "X\<in> parts H ==> \<exists>Y\<in>H. X\<in> parts {Y}"
   204 by (erule parts.induct, fast+)
   205 
   206 
   207 subsubsection{*Unions *}
   208 
   209 lemma parts_Un_subset1: "parts(G) \<union> parts(H) \<subseteq> parts(G \<union> H)"
   210 by (intro Un_least parts_mono Un_upper1 Un_upper2)
   211 
   212 lemma parts_Un_subset2: "parts(G \<union> H) \<subseteq> parts(G) \<union> parts(H)"
   213 apply (rule subsetI)
   214 apply (erule parts.induct, blast+)
   215 done
   216 
   217 lemma parts_Un [simp]: "parts(G \<union> H) = parts(G) \<union> parts(H)"
   218 by (intro equalityI parts_Un_subset1 parts_Un_subset2)
   219 
   220 lemma parts_insert: "parts (insert X H) = parts {X} \<union> parts H"
   221 apply (subst insert_is_Un [of _ H])
   222 apply (simp only: parts_Un)
   223 done
   224 
   225 text{*TWO inserts to avoid looping.  This rewrite is better than nothing.
   226   Not suitable for Addsimps: its behaviour can be strange.*}
   227 lemma parts_insert2:
   228      "parts (insert X (insert Y H)) = parts {X} \<union> parts {Y} \<union> parts H"
   229 apply (simp add: Un_assoc)
   230 apply (simp add: parts_insert [symmetric])
   231 done
   232 
   233 lemma parts_UN_subset1: "(\<Union>x\<in>A. parts(H x)) \<subseteq> parts(\<Union>x\<in>A. H x)"
   234 by (intro UN_least parts_mono UN_upper)
   235 
   236 lemma parts_UN_subset2: "parts(\<Union>x\<in>A. H x) \<subseteq> (\<Union>x\<in>A. parts(H x))"
   237 apply (rule subsetI)
   238 apply (erule parts.induct, blast+)
   239 done
   240 
   241 lemma parts_UN [simp]: "parts(\<Union>x\<in>A. H x) = (\<Union>x\<in>A. parts(H x))"
   242 by (intro equalityI parts_UN_subset1 parts_UN_subset2)
   243 
   244 text{*Added to simplify arguments to parts, analz and synth.
   245   NOTE: the UN versions are no longer used!*}
   246 
   247 
   248 text{*This allows @{text blast} to simplify occurrences of 
   249   @{term "parts(G\<union>H)"} in the assumption.*}
   250 lemmas in_parts_UnE = parts_Un [THEN equalityD1, THEN subsetD, THEN UnE] 
   251 declare in_parts_UnE [elim!]
   252 
   253 
   254 lemma parts_insert_subset: "insert X (parts H) \<subseteq> parts(insert X H)"
   255 by (blast intro: parts_mono [THEN [2] rev_subsetD])
   256 
   257 subsubsection{*Idempotence and transitivity *}
   258 
   259 lemma parts_partsD [dest!]: "X\<in> parts (parts H) ==> X\<in> parts H"
   260 by (erule parts.induct, blast+)
   261 
   262 lemma parts_idem [simp]: "parts (parts H) = parts H"
   263 by blast
   264 
   265 lemma parts_subset_iff [simp]: "(parts G \<subseteq> parts H) = (G \<subseteq> parts H)"
   266 apply (rule iffI)
   267 apply (iprover intro: subset_trans parts_increasing)  
   268 apply (frule parts_mono, simp) 
   269 done
   270 
   271 lemma parts_trans: "[| X\<in> parts G;  G \<subseteq> parts H |] ==> X\<in> parts H"
   272 by (drule parts_mono, blast)
   273 
   274 text{*Cut*}
   275 lemma parts_cut:
   276      "[| Y\<in> parts (insert X G);  X\<in> parts H |] ==> Y\<in> parts (G \<union> H)" 
   277 by (blast intro: parts_trans) 
   278 
   279 
   280 lemma parts_cut_eq [simp]: "X\<in> parts H ==> parts (insert X H) = parts H"
   281 by (force dest!: parts_cut intro: parts_insertI)
   282 
   283 
   284 subsubsection{*Rewrite rules for pulling out atomic messages *}
   285 
   286 lemmas parts_insert_eq_I = equalityI [OF subsetI parts_insert_subset]
   287 
   288 
   289 lemma parts_insert_Agent [simp]:
   290      "parts (insert (Agent agt) H) = insert (Agent agt) (parts H)"
   291 apply (rule parts_insert_eq_I) 
   292 apply (erule parts.induct, auto) 
   293 done
   294 
   295 lemma parts_insert_Nonce [simp]:
   296      "parts (insert (Nonce N) H) = insert (Nonce N) (parts H)"
   297 apply (rule parts_insert_eq_I) 
   298 apply (erule parts.induct, auto) 
   299 done
   300 
   301 lemma parts_insert_Key [simp]:
   302      "parts (insert (Key K) H) = insert (Key K) (parts H)"
   303 apply (rule parts_insert_eq_I) 
   304 apply (erule parts.induct, auto) 
   305 done
   306 
   307 lemma parts_insert_Crypt [simp]:
   308      "parts (insert (Crypt K X) H) = insert (Crypt K X) (parts (insert X H))"
   309 apply (rule equalityI)
   310 apply (rule subsetI)
   311 apply (erule parts.induct, auto)
   312 apply (blast intro: parts.Body)
   313 done
   314 
   315 lemma parts_insert_MPair [simp]:
   316      "parts (insert {|X,Y|} H) =  
   317           insert {|X,Y|} (parts (insert X (insert Y H)))"
   318 apply (rule equalityI)
   319 apply (rule subsetI)
   320 apply (erule parts.induct, auto)
   321 apply (blast intro: parts.Fst parts.Snd)+
   322 done
   323 
   324 lemma parts_image_Key [simp]: "parts (Key`N) = Key`N"
   325 apply auto
   326 apply (erule parts.induct, auto)
   327 done
   328 
   329 
   330 text{*In any message, there is an upper bound N on its greatest nonce.*}
   331 lemma msg_Nonce_supply: "\<exists>N. \<forall>n. N\<le>n --> Nonce n \<notin> parts {msg}"
   332 apply (induct_tac "msg")
   333 apply (simp_all (no_asm_simp) add: exI parts_insert2)
   334  txt{*MPair case: blast works out the necessary sum itself!*}
   335  prefer 2 apply auto apply (blast elim!: add_leE)
   336 txt{*Nonce case*}
   337 apply (rule_tac x = "N + Suc nat" in exI, auto) 
   338 done
   339 (*>*)
   340 
   341 section{* Modelling the Adversary *}
   342 
   343 text {*
   344 The spy is part of the system and must be built into the model.  He is
   345 a malicious user who does not have to follow the protocol.  He
   346 watches the network and uses any keys he knows to decrypt messages.
   347 Thus he accumulates additional keys and nonces.  These he can use to
   348 compose new messages, which he may send to anybody.  
   349 
   350 Two functions enable us to formalize this behaviour: @{text analz} and
   351 @{text synth}.  Each function maps a sets of messages to another set of
   352 messages. The set @{text "analz H"} formalizes what the adversary can learn
   353 from the set of messages~$H$.  The closure properties of this set are
   354 defined inductively.
   355 *}
   356 
   357 inductive_set
   358   analz :: "msg set \<Rightarrow> msg set"
   359   for H :: "msg set"
   360   where
   361     Inj [intro,simp] : "X \<in> H \<Longrightarrow> X \<in> analz H"
   362   | Fst:     "\<lbrace>X,Y\<rbrace> \<in> analz H \<Longrightarrow> X \<in> analz H"
   363   | Snd:     "\<lbrace>X,Y\<rbrace> \<in> analz H \<Longrightarrow> Y \<in> analz H"
   364   | Decrypt [dest]: 
   365              "\<lbrakk>Crypt K X \<in> analz H; Key(invKey K) \<in> analz H\<rbrakk>
   366               \<Longrightarrow> X \<in> analz H"
   367 (*<*)
   368 text{*Monotonicity; Lemma 1 of Lowe's paper*}
   369 lemma analz_mono: "G\<subseteq>H ==> analz(G) \<subseteq> analz(H)"
   370 apply auto
   371 apply (erule analz.induct) 
   372 apply (auto dest: analz.Fst analz.Snd) 
   373 done
   374 
   375 text{*Making it safe speeds up proofs*}
   376 lemma MPair_analz [elim!]:
   377      "[| {|X,Y|} \<in> analz H;        
   378              [| X \<in> analz H; Y \<in> analz H |] ==> P   
   379           |] ==> P"
   380 by (blast dest: analz.Fst analz.Snd)
   381 
   382 lemma analz_increasing: "H \<subseteq> analz(H)"
   383 by blast
   384 
   385 lemma analz_subset_parts: "analz H \<subseteq> parts H"
   386 apply (rule subsetI)
   387 apply (erule analz.induct, blast+)
   388 done
   389 
   390 lemmas analz_into_parts = analz_subset_parts [THEN subsetD, standard]
   391 
   392 lemmas not_parts_not_analz = analz_subset_parts [THEN contra_subsetD, standard]
   393 
   394 
   395 lemma parts_analz [simp]: "parts (analz H) = parts H"
   396 apply (rule equalityI)
   397 apply (rule analz_subset_parts [THEN parts_mono, THEN subset_trans], simp)
   398 apply (blast intro: analz_increasing [THEN parts_mono, THEN subsetD])
   399 done
   400 
   401 lemma analz_parts [simp]: "analz (parts H) = parts H"
   402 apply auto
   403 apply (erule analz.induct, auto)
   404 done
   405 
   406 lemmas analz_insertI = subset_insertI [THEN analz_mono, THEN [2] rev_subsetD, standard]
   407 
   408 subsubsection{*General equational properties *}
   409 
   410 lemma analz_empty [simp]: "analz{} = {}"
   411 apply safe
   412 apply (erule analz.induct, blast+)
   413 done
   414 
   415 text{*Converse fails: we can analz more from the union than from the 
   416   separate parts, as a key in one might decrypt a message in the other*}
   417 lemma analz_Un: "analz(G) \<union> analz(H) \<subseteq> analz(G \<union> H)"
   418 by (intro Un_least analz_mono Un_upper1 Un_upper2)
   419 
   420 lemma analz_insert: "insert X (analz H) \<subseteq> analz(insert X H)"
   421 by (blast intro: analz_mono [THEN [2] rev_subsetD])
   422 
   423 subsubsection{*Rewrite rules for pulling out atomic messages *}
   424 
   425 lemmas analz_insert_eq_I = equalityI [OF subsetI analz_insert]
   426 
   427 lemma analz_insert_Agent [simp]:
   428      "analz (insert (Agent agt) H) = insert (Agent agt) (analz H)"
   429 apply (rule analz_insert_eq_I) 
   430 apply (erule analz.induct, auto) 
   431 done
   432 
   433 lemma analz_insert_Nonce [simp]:
   434      "analz (insert (Nonce N) H) = insert (Nonce N) (analz H)"
   435 apply (rule analz_insert_eq_I) 
   436 apply (erule analz.induct, auto) 
   437 done
   438 
   439 text{*Can only pull out Keys if they are not needed to decrypt the rest*}
   440 lemma analz_insert_Key [simp]: 
   441     "K \<notin> keysFor (analz H) ==>   
   442           analz (insert (Key K) H) = insert (Key K) (analz H)"
   443 apply (unfold keysFor_def)
   444 apply (rule analz_insert_eq_I) 
   445 apply (erule analz.induct, auto) 
   446 done
   447 
   448 lemma analz_insert_MPair [simp]:
   449      "analz (insert {|X,Y|} H) =  
   450           insert {|X,Y|} (analz (insert X (insert Y H)))"
   451 apply (rule equalityI)
   452 apply (rule subsetI)
   453 apply (erule analz.induct, auto)
   454 apply (erule analz.induct)
   455 apply (blast intro: analz.Fst analz.Snd)+
   456 done
   457 
   458 text{*Can pull out enCrypted message if the Key is not known*}
   459 lemma analz_insert_Crypt:
   460      "Key (invKey K) \<notin> analz H 
   461       ==> analz (insert (Crypt K X) H) = insert (Crypt K X) (analz H)"
   462 apply (rule analz_insert_eq_I) 
   463 apply (erule analz.induct, auto) 
   464 
   465 done
   466 
   467 lemma lemma1: "Key (invKey K) \<in> analz H ==>   
   468                analz (insert (Crypt K X) H) \<subseteq>  
   469                insert (Crypt K X) (analz (insert X H))"
   470 apply (rule subsetI)
   471 apply (erule_tac x = x in analz.induct, auto)
   472 done
   473 
   474 lemma lemma2: "Key (invKey K) \<in> analz H ==>   
   475                insert (Crypt K X) (analz (insert X H)) \<subseteq>  
   476                analz (insert (Crypt K X) H)"
   477 apply auto
   478 apply (erule_tac x = x in analz.induct, auto)
   479 apply (blast intro: analz_insertI analz.Decrypt)
   480 done
   481 
   482 lemma analz_insert_Decrypt:
   483      "Key (invKey K) \<in> analz H ==>   
   484                analz (insert (Crypt K X) H) =  
   485                insert (Crypt K X) (analz (insert X H))"
   486 by (intro equalityI lemma1 lemma2)
   487 
   488 text{*Case analysis: either the message is secure, or it is not! Effective,
   489 but can cause subgoals to blow up! Use with @{text "split_if"}; apparently
   490 @{text "split_tac"} does not cope with patterns such as @{term"analz (insert
   491 (Crypt K X) H)"} *} 
   492 lemma analz_Crypt_if [simp]:
   493      "analz (insert (Crypt K X) H) =                 
   494           (if (Key (invKey K) \<in> analz H)                 
   495            then insert (Crypt K X) (analz (insert X H))  
   496            else insert (Crypt K X) (analz H))"
   497 by (simp add: analz_insert_Crypt analz_insert_Decrypt)
   498 
   499 
   500 text{*This rule supposes "for the sake of argument" that we have the key.*}
   501 lemma analz_insert_Crypt_subset:
   502      "analz (insert (Crypt K X) H) \<subseteq>   
   503            insert (Crypt K X) (analz (insert X H))"
   504 apply (rule subsetI)
   505 apply (erule analz.induct, auto)
   506 done
   507 
   508 
   509 lemma analz_image_Key [simp]: "analz (Key`N) = Key`N"
   510 apply auto
   511 apply (erule analz.induct, auto)
   512 done
   513 
   514 
   515 subsubsection{*Idempotence and transitivity *}
   516 
   517 lemma analz_analzD [dest!]: "X\<in> analz (analz H) ==> X\<in> analz H"
   518 by (erule analz.induct, blast+)
   519 
   520 lemma analz_idem [simp]: "analz (analz H) = analz H"
   521 by blast
   522 
   523 lemma analz_subset_iff [simp]: "(analz G \<subseteq> analz H) = (G \<subseteq> analz H)"
   524 apply (rule iffI)
   525 apply (iprover intro: subset_trans analz_increasing)  
   526 apply (frule analz_mono, simp) 
   527 done
   528 
   529 lemma analz_trans: "[| X\<in> analz G;  G \<subseteq> analz H |] ==> X\<in> analz H"
   530 by (drule analz_mono, blast)
   531 
   532 text{*Cut; Lemma 2 of Lowe*}
   533 lemma analz_cut: "[| Y\<in> analz (insert X H);  X\<in> analz H |] ==> Y\<in> analz H"
   534 by (erule analz_trans, blast)
   535 
   536 (*Cut can be proved easily by induction on
   537    "Y: analz (insert X H) ==> X: analz H --> Y: analz H"
   538 *)
   539 
   540 text{*This rewrite rule helps in the simplification of messages that involve
   541   the forwarding of unknown components (X).  Without it, removing occurrences
   542   of X can be very complicated. *}
   543 lemma analz_insert_eq: "X\<in> analz H ==> analz (insert X H) = analz H"
   544 by (blast intro: analz_cut analz_insertI)
   545 
   546 
   547 text{*A congruence rule for "analz" *}
   548 
   549 lemma analz_subset_cong:
   550      "[| analz G \<subseteq> analz G'; analz H \<subseteq> analz H' |] 
   551       ==> analz (G \<union> H) \<subseteq> analz (G' \<union> H')"
   552 apply simp
   553 apply (iprover intro: conjI subset_trans analz_mono Un_upper1 Un_upper2) 
   554 done
   555 
   556 lemma analz_cong:
   557      "[| analz G = analz G'; analz H = analz H' |] 
   558       ==> analz (G \<union> H) = analz (G' \<union> H')"
   559 by (intro equalityI analz_subset_cong, simp_all) 
   560 
   561 lemma analz_insert_cong:
   562      "analz H = analz H' ==> analz(insert X H) = analz(insert X H')"
   563 by (force simp only: insert_def intro!: analz_cong)
   564 
   565 text{*If there are no pairs or encryptions then analz does nothing*}
   566 lemma analz_trivial:
   567      "[| \<forall>X Y. {|X,Y|} \<notin> H;  \<forall>X K. Crypt K X \<notin> H |] ==> analz H = H"
   568 apply safe
   569 apply (erule analz.induct, blast+)
   570 done
   571 
   572 text{*These two are obsolete (with a single Spy) but cost little to prove...*}
   573 lemma analz_UN_analz_lemma:
   574      "X\<in> analz (\<Union>i\<in>A. analz (H i)) ==> X\<in> analz (\<Union>i\<in>A. H i)"
   575 apply (erule analz.induct)
   576 apply (blast intro: analz_mono [THEN [2] rev_subsetD])+
   577 done
   578 
   579 lemma analz_UN_analz [simp]: "analz (\<Union>i\<in>A. analz (H i)) = analz (\<Union>i\<in>A. H i)"
   580 by (blast intro: analz_UN_analz_lemma analz_mono [THEN [2] rev_subsetD])
   581 (*>*)
   582 text {*
   583 Note the @{text Decrypt} rule: the spy can decrypt a
   584 message encrypted with key~$K$ if he has the matching key,~$K^{-1}$. 
   585 Properties proved by rule induction include the following:
   586 @{named_thms [display,indent=0] analz_mono [no_vars] (analz_mono) analz_idem [no_vars] (analz_idem)}
   587 
   588 The set of fake messages that an intruder could invent
   589 starting from~@{text H} is @{text "synth(analz H)"}, where @{text "synth H"}
   590 formalizes what the adversary can build from the set of messages~$H$.  
   591 *}
   592 
   593 inductive_set
   594   synth :: "msg set \<Rightarrow> msg set"
   595   for H :: "msg set"
   596   where
   597     Inj    [intro]: "X \<in> H \<Longrightarrow> X \<in> synth H"
   598   | Agent  [intro]: "Agent agt \<in> synth H"
   599   | MPair  [intro]:
   600               "\<lbrakk>X \<in> synth H;  Y \<in> synth H\<rbrakk> \<Longrightarrow> \<lbrace>X,Y\<rbrace> \<in> synth H"
   601   | Crypt  [intro]:
   602               "\<lbrakk>X \<in> synth H;  Key K \<in> H\<rbrakk> \<Longrightarrow> Crypt K X \<in> synth H"
   603 (*<*)
   604 lemma synth_mono: "G\<subseteq>H ==> synth(G) \<subseteq> synth(H)"
   605   by (auto, erule synth.induct, auto)  
   606 
   607 inductive_cases Key_synth   [elim!]: "Key K \<in> synth H"
   608 inductive_cases MPair_synth [elim!]: "{|X,Y|} \<in> synth H"
   609 inductive_cases Crypt_synth [elim!]: "Crypt K X \<in> synth H"
   610 
   611 lemma analz_synth_Un [simp]: "analz (synth G \<union> H) = analz (G \<union> H) \<union> synth G"
   612 apply (rule equalityI)
   613 apply (rule subsetI)
   614 apply (erule analz.induct)
   615 prefer 5 apply (blast intro: analz_mono [THEN [2] rev_subsetD])
   616 apply (blast intro: analz.Fst analz.Snd analz.Decrypt)+
   617 done
   618 
   619 lemma analz_synth [simp]: "analz (synth H) = analz H \<union> synth H"
   620 apply (cut_tac H = "{}" in analz_synth_Un)
   621 apply (simp (no_asm_use))
   622 done
   623 (*>*)
   624 text {*
   625 The set includes all agent names.  Nonces and keys are assumed to be
   626 unguessable, so none are included beyond those already in~$H$.   Two
   627 elements of @{term "synth H"} can be combined, and an element can be encrypted
   628 using a key present in~$H$.
   629 
   630 Like @{text analz}, this set operator is monotone and idempotent.  It also
   631 satisfies an interesting equation involving @{text analz}:
   632 @{named_thms [display,indent=0] analz_synth [no_vars] (analz_synth)}
   633 Rule inversion plays a major role in reasoning about @{text synth}, through
   634 declarations such as this one:
   635 *}
   636 
   637 inductive_cases Nonce_synth [elim!]: "Nonce n \<in> synth H"
   638 
   639 text {*
   640 \noindent
   641 The resulting elimination rule replaces every assumption of the form
   642 @{term "Nonce n \<in> synth H"} by @{term "Nonce n \<in> H"},
   643 expressing that a nonce cannot be guessed.  
   644 
   645 A third operator, @{text parts}, is useful for stating correctness
   646 properties.  The set
   647 @{term "parts H"} consists of the components of elements of~$H$.  This set
   648 includes~@{text H} and is closed under the projections from a compound
   649 message to its immediate parts. 
   650 Its definition resembles that of @{text analz} except in the rule
   651 corresponding to the constructor @{text Crypt}: 
   652 @{thm [display,indent=5] parts.Body [no_vars]}
   653 The body of an encrypted message is always regarded as part of it.  We can
   654 use @{text parts} to express general well-formedness properties of a protocol,
   655 for example, that an uncompromised agent's private key will never be
   656 included as a component of any message.
   657 *}
   658 (*<*)
   659 lemma synth_increasing: "H \<subseteq> synth(H)"
   660 by blast
   661 
   662 subsubsection{*Unions *}
   663 
   664 text{*Converse fails: we can synth more from the union than from the 
   665   separate parts, building a compound message using elements of each.*}
   666 lemma synth_Un: "synth(G) \<union> synth(H) \<subseteq> synth(G \<union> H)"
   667 by (intro Un_least synth_mono Un_upper1 Un_upper2)
   668 
   669 lemma synth_insert: "insert X (synth H) \<subseteq> synth(insert X H)"
   670 by (blast intro: synth_mono [THEN [2] rev_subsetD])
   671 
   672 subsubsection{*Idempotence and transitivity *}
   673 
   674 lemma synth_synthD [dest!]: "X\<in> synth (synth H) ==> X\<in> synth H"
   675 by (erule synth.induct, blast+)
   676 
   677 lemma synth_idem: "synth (synth H) = synth H"
   678 by blast
   679 
   680 lemma synth_subset_iff [simp]: "(synth G \<subseteq> synth H) = (G \<subseteq> synth H)"
   681 apply (rule iffI)
   682 apply (iprover intro: subset_trans synth_increasing)  
   683 apply (frule synth_mono, simp add: synth_idem) 
   684 done
   685 
   686 lemma synth_trans: "[| X\<in> synth G;  G \<subseteq> synth H |] ==> X\<in> synth H"
   687 by (drule synth_mono, blast)
   688 
   689 text{*Cut; Lemma 2 of Lowe*}
   690 lemma synth_cut: "[| Y\<in> synth (insert X H);  X\<in> synth H |] ==> Y\<in> synth H"
   691 by (erule synth_trans, blast)
   692 
   693 lemma Agent_synth [simp]: "Agent A \<in> synth H"
   694 by blast
   695 
   696 lemma Nonce_synth_eq [simp]: "(Nonce N \<in> synth H) = (Nonce N \<in> H)"
   697 by blast
   698 
   699 lemma Key_synth_eq [simp]: "(Key K \<in> synth H) = (Key K \<in> H)"
   700 by blast
   701 
   702 lemma Crypt_synth_eq [simp]:
   703      "Key K \<notin> H ==> (Crypt K X \<in> synth H) = (Crypt K X \<in> H)"
   704 by blast
   705 
   706 
   707 lemma keysFor_synth [simp]: 
   708     "keysFor (synth H) = keysFor H \<union> invKey`{K. Key K \<in> H}"
   709 by (unfold keysFor_def, blast)
   710 
   711 
   712 subsubsection{*Combinations of parts, analz and synth *}
   713 
   714 lemma parts_synth [simp]: "parts (synth H) = parts H \<union> synth H"
   715 apply (rule equalityI)
   716 apply (rule subsetI)
   717 apply (erule parts.induct)
   718 apply (blast intro: synth_increasing [THEN parts_mono, THEN subsetD] 
   719                     parts.Fst parts.Snd parts.Body)+
   720 done
   721 
   722 lemma analz_analz_Un [simp]: "analz (analz G \<union> H) = analz (G \<union> H)"
   723 apply (intro equalityI analz_subset_cong)+
   724 apply simp_all
   725 done
   726 
   727 
   728 subsubsection{*For reasoning about the Fake rule in traces *}
   729 
   730 lemma parts_insert_subset_Un: "X\<in> G ==> parts(insert X H) \<subseteq> parts G \<union> parts H"
   731 by (rule subset_trans [OF parts_mono parts_Un_subset2], blast)
   732 
   733 text{*More specifically for Fake.  Very occasionally we could do with a version
   734   of the form  @{term"parts{X} \<subseteq> synth (analz H) \<union> parts H"} *}
   735 lemma Fake_parts_insert:
   736      "X \<in> synth (analz H) ==>  
   737       parts (insert X H) \<subseteq> synth (analz H) \<union> parts H"
   738 apply (drule parts_insert_subset_Un)
   739 apply (simp (no_asm_use))
   740 apply blast
   741 done
   742 
   743 lemma Fake_parts_insert_in_Un:
   744      "[|Z \<in> parts (insert X H);  X: synth (analz H)|] 
   745       ==> Z \<in>  synth (analz H) \<union> parts H";
   746 by (blast dest: Fake_parts_insert  [THEN subsetD, dest])
   747 
   748 text{*@{term H} is sometimes @{term"Key ` KK \<union> spies evs"}, so can't put 
   749   @{term "G=H"}.*}
   750 lemma Fake_analz_insert:
   751      "X\<in> synth (analz G) ==>  
   752       analz (insert X H) \<subseteq> synth (analz G) \<union> analz (G \<union> H)"
   753 apply (rule subsetI)
   754 apply (subgoal_tac "x \<in> analz (synth (analz G) \<union> H) ")
   755 prefer 2 apply (blast intro: analz_mono [THEN [2] rev_subsetD] analz_mono [THEN synth_mono, THEN [2] rev_subsetD])
   756 apply (simp (no_asm_use))
   757 apply blast
   758 done
   759 
   760 lemma analz_conj_parts [simp]:
   761      "(X \<in> analz H & X \<in> parts H) = (X \<in> analz H)"
   762 by (blast intro: analz_subset_parts [THEN subsetD])
   763 
   764 lemma analz_disj_parts [simp]:
   765      "(X \<in> analz H | X \<in> parts H) = (X \<in> parts H)"
   766 by (blast intro: analz_subset_parts [THEN subsetD])
   767 
   768 text{*Without this equation, other rules for synth and analz would yield
   769   redundant cases*}
   770 lemma MPair_synth_analz [iff]:
   771      "({|X,Y|} \<in> synth (analz H)) =  
   772       (X \<in> synth (analz H) & Y \<in> synth (analz H))"
   773 by blast
   774 
   775 lemma Crypt_synth_analz:
   776      "[| Key K \<in> analz H;  Key (invKey K) \<in> analz H |]  
   777        ==> (Crypt K X \<in> synth (analz H)) = (X \<in> synth (analz H))"
   778 by blast
   779 
   780 
   781 text{*We do NOT want Crypt... messages broken up in protocols!!*}
   782 declare parts.Body [rule del]
   783 
   784 
   785 text{*Rewrites to push in Key and Crypt messages, so that other messages can
   786     be pulled out using the @{text analz_insert} rules*}
   787 
   788 lemmas pushKeys [standard] =
   789   insert_commute [of "Key K" "Agent C"]
   790   insert_commute [of "Key K" "Nonce N"]
   791   insert_commute [of "Key K" "Number N"]
   792   insert_commute [of "Key K" "Hash X"]
   793   insert_commute [of "Key K" "MPair X Y"]
   794   insert_commute [of "Key K" "Crypt X K'"]
   795 
   796 lemmas pushCrypts [standard] =
   797   insert_commute [of "Crypt X K" "Agent C"]
   798   insert_commute [of "Crypt X K" "Agent C"]
   799   insert_commute [of "Crypt X K" "Nonce N"]
   800   insert_commute [of "Crypt X K" "Number N"]
   801   insert_commute [of "Crypt X K" "Hash X'"]
   802   insert_commute [of "Crypt X K" "MPair X' Y"]
   803 
   804 text{*Cannot be added with @{text "[simp]"} -- messages should not always be
   805   re-ordered. *}
   806 lemmas pushes = pushKeys pushCrypts
   807 
   808 
   809 subsection{*Tactics useful for many protocol proofs*}
   810 ML
   811 {*
   812 val invKey = thm "invKey"
   813 val keysFor_def = thm "keysFor_def"
   814 val symKeys_def = thm "symKeys_def"
   815 val parts_mono = thm "parts_mono";
   816 val analz_mono = thm "analz_mono";
   817 val synth_mono = thm "synth_mono";
   818 val analz_increasing = thm "analz_increasing";
   819 
   820 val analz_insertI = thm "analz_insertI";
   821 val analz_subset_parts = thm "analz_subset_parts";
   822 val Fake_parts_insert = thm "Fake_parts_insert";
   823 val Fake_analz_insert = thm "Fake_analz_insert";
   824 val pushes = thms "pushes";
   825 
   826 
   827 (*Prove base case (subgoal i) and simplify others.  A typical base case
   828   concerns  Crypt K X \<notin> Key`shrK`bad  and cannot be proved by rewriting
   829   alone.*)
   830 fun prove_simple_subgoals_tac (cs, ss) i = 
   831     force_tac (cs, ss addsimps [@{thm image_eq_UN}]) i THEN
   832     ALLGOALS (asm_simp_tac ss)
   833 
   834 (*Analysis of Fake cases.  Also works for messages that forward unknown parts,
   835   but this application is no longer necessary if analz_insert_eq is used.
   836   Abstraction over i is ESSENTIAL: it delays the dereferencing of claset
   837   DEPENDS UPON "X" REFERRING TO THE FRADULENT MESSAGE *)
   838 
   839 (*Apply rules to break down assumptions of the form
   840   Y \<in> parts(insert X H)  and  Y \<in> analz(insert X H)
   841 *)
   842 fun impOfSubs th = th RSN (2, @{thm rev_subsetD})
   843 
   844 val Fake_insert_tac = 
   845     dresolve_tac [impOfSubs Fake_analz_insert,
   846                   impOfSubs Fake_parts_insert] THEN'
   847     eresolve_tac [asm_rl, thm"synth.Inj"];
   848 
   849 fun Fake_insert_simp_tac ss i = 
   850     REPEAT (Fake_insert_tac i) THEN asm_full_simp_tac ss i;
   851 
   852 fun atomic_spy_analz_tac (cs,ss) = SELECT_GOAL
   853     (Fake_insert_simp_tac ss 1
   854      THEN
   855      IF_UNSOLVED (Blast.depth_tac
   856                   (cs addIs [analz_insertI,
   857                                    impOfSubs analz_subset_parts]) 4 1))
   858 
   859 fun spy_analz_tac (cs,ss) i =
   860   DETERM
   861    (SELECT_GOAL
   862      (EVERY 
   863       [  (*push in occurrences of X...*)
   864        (REPEAT o CHANGED)
   865            (res_inst_tac (Simplifier.the_context ss)
   866             [(("x", 1), "X")] (insert_commute RS ssubst) 1),
   867        (*...allowing further simplifications*)
   868        simp_tac ss 1,
   869        REPEAT (FIRSTGOAL (resolve_tac [allI,impI,notI,conjI,iffI])),
   870        DEPTH_SOLVE (atomic_spy_analz_tac (cs,ss) 1)]) i)
   871 *}
   872 
   873 text{*By default only @{text o_apply} is built-in.  But in the presence of
   874 eta-expansion this means that some terms displayed as @{term "f o g"} will be
   875 rewritten, and others will not!*}
   876 declare o_def [simp]
   877 
   878 
   879 lemma Crypt_notin_image_Key [simp]: "Crypt K X \<notin> Key ` A"
   880 by auto
   881 
   882 lemma synth_analz_mono: "G\<subseteq>H ==> synth (analz(G)) \<subseteq> synth (analz(H))"
   883 by (iprover intro: synth_mono analz_mono) 
   884 
   885 lemma Fake_analz_eq [simp]:
   886      "X \<in> synth(analz H) ==> synth (analz (insert X H)) = synth (analz H)"
   887 apply (drule Fake_analz_insert[of _ _ "H"])
   888 apply (simp add: synth_increasing[THEN Un_absorb2])
   889 apply (drule synth_mono)
   890 apply (simp add: synth_idem)
   891 apply (rule equalityI)
   892 apply (simp add: );
   893 apply (rule synth_analz_mono, blast)   
   894 done
   895 
   896 text{*Two generalizations of @{text analz_insert_eq}*}
   897 lemma gen_analz_insert_eq [rule_format]:
   898      "X \<in> analz H ==> ALL G. H \<subseteq> G --> analz (insert X G) = analz G";
   899 by (blast intro: analz_cut analz_insertI analz_mono [THEN [2] rev_subsetD])
   900 
   901 lemma synth_analz_insert_eq [rule_format]:
   902      "X \<in> synth (analz H) 
   903       ==> ALL G. H \<subseteq> G --> (Key K \<in> analz (insert X G)) = (Key K \<in> analz G)";
   904 apply (erule synth.induct) 
   905 apply (simp_all add: gen_analz_insert_eq subset_trans [OF _ subset_insertI]) 
   906 done
   907 
   908 lemma Fake_parts_sing:
   909      "X \<in> synth (analz H) ==> parts{X} \<subseteq> synth (analz H) \<union> parts H";
   910 apply (rule subset_trans) 
   911  apply (erule_tac [2] Fake_parts_insert)
   912 apply (rule parts_mono, blast)
   913 done
   914 
   915 lemmas Fake_parts_sing_imp_Un = Fake_parts_sing [THEN [2] rev_subsetD]
   916 
   917 method_setup spy_analz = {*
   918     Scan.succeed (SIMPLE_METHOD' o spy_analz_tac o clasimpset_of) *}
   919     "for proving the Fake case when analz is involved"
   920 
   921 method_setup atomic_spy_analz = {*
   922     Scan.succeed (SIMPLE_METHOD' o atomic_spy_analz_tac o clasimpset_of) *}
   923     "for debugging spy_analz"
   924 
   925 method_setup Fake_insert_simp = {*
   926     Scan.succeed (SIMPLE_METHOD' o Fake_insert_simp_tac o simpset_of) *}
   927     "for debugging spy_analz"
   928 
   929 
   930 end
   931 (*>*)