| author | wenzelm | 
| Wed, 12 May 2021 16:47:52 +0200 | |
| changeset 73687 | 54fe8cc0e1c6 | 
| parent 69597 | ff784d5a5bfb | 
| child 76338 | e4fa45571bab | 
| permissions | -rw-r--r-- | 
| 33028 | 1 | (* Title: HOL/SET_Protocol/Message_SET.thy | 
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32149diff
changeset | 2 | Author: Giampaolo Bella | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32149diff
changeset | 3 | Author: Fabio Massacci | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
32149diff
changeset | 4 | Author: Lawrence C Paulson | 
| 14199 | 5 | *) | 
| 6 | ||
| 63167 | 7 | section\<open>The Message Theory, Modified for SET\<close> | 
| 14199 | 8 | |
| 33028 | 9 | theory Message_SET | 
| 66453 
cc19f7ca2ed6
session-qualified theory imports: isabelle imports -U -i -d '~~/src/Benchmarks' -a;
 wenzelm parents: 
63167diff
changeset | 10 | imports Main "HOL-Library.Nat_Bijection" | 
| 25592 | 11 | begin | 
| 14199 | 12 | |
| 63167 | 13 | subsection\<open>General Lemmas\<close> | 
| 14199 | 14 | |
| 63167 | 15 | text\<open>Needed occasionally with \<open>spy_analz_tac\<close>, e.g. in | 
| 16 | \<open>analz_insert_Key_newK\<close>\<close> | |
| 14199 | 17 | |
| 18 | lemma Un_absorb3 [simp] : "A \<union> (B \<union> A) = B \<union> A" | |
| 19 | by blast | |
| 20 | ||
| 63167 | 21 | text\<open>Collapses redundant cases in the huge protocol proofs\<close> | 
| 14199 | 22 | lemmas disj_simps = disj_comms disj_left_absorb disj_assoc | 
| 23 | ||
| 69597 | 24 | text\<open>Effective with assumptions like \<^term>\<open>K \<notin> range pubK\<close> and | 
| 25 | \<^term>\<open>K \<notin> invKey`range pubK\<close>\<close> | |
| 14199 | 26 | lemma notin_image_iff: "(y \<notin> f`I) = (\<forall>i\<in>I. f i \<noteq> y)" | 
| 27 | by blast | |
| 28 | ||
| 69597 | 29 | text\<open>Effective with the assumption \<^term>\<open>KK \<subseteq> - (range(invKey o pubK))\<close>\<close> | 
| 67613 | 30 | lemma disjoint_image_iff: "(A \<subseteq> - (f`I)) = (\<forall>i\<in>I. f i \<notin> A)" | 
| 14199 | 31 | by blast | 
| 32 | ||
| 33 | ||
| 34 | ||
| 42463 | 35 | type_synonym key = nat | 
| 14199 | 36 | |
| 37 | consts | |
| 67443 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 38 | all_symmetric :: bool \<comment> \<open>true if all keys are symmetric\<close> | 
| 67613 | 39 | invKey :: "key\<Rightarrow>key" \<comment> \<open>inverse of a symmetric key\<close> | 
| 14199 | 40 | |
| 41 | specification (invKey) | |
| 42 | invKey [simp]: "invKey (invKey K) = K" | |
| 67613 | 43 | invKey_symmetric: "all_symmetric \<longrightarrow> invKey = id" | 
| 14199 | 44 | by (rule exI [of _ id], auto) | 
| 45 | ||
| 46 | ||
| 63167 | 47 | text\<open>The inverse of a symmetric key is itself; that of a public key | 
| 48 | is the private key and vice versa\<close> | |
| 14199 | 49 | |
| 35416 
d8d7d1b785af
replaced a couple of constsdefs by definitions (also some old primrecs by modern ones)
 haftmann parents: 
35068diff
changeset | 50 | definition symKeys :: "key set" where | 
| 14199 | 51 |   "symKeys == {K. invKey K = K}"
 | 
| 52 | ||
| 63167 | 53 | text\<open>Agents. We allow any number of certification authorities, cardholders | 
| 54 | merchants, and payment gateways.\<close> | |
| 58310 | 55 | datatype | 
| 14199 | 56 | agent = CA nat | Cardholder nat | Merchant nat | PG nat | Spy | 
| 57 | ||
| 63167 | 58 | text\<open>Messages\<close> | 
| 58310 | 59 | datatype | 
| 67443 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 60 | msg = Agent agent \<comment> \<open>Agent names\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 61 | | Number nat \<comment> \<open>Ordinary integers, timestamps, ...\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 62 | | Nonce nat \<comment> \<open>Unguessable nonces\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 63 | | Pan nat \<comment> \<open>Unguessable Primary Account Numbers (??)\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 64 | | Key key \<comment> \<open>Crypto keys\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 65 | | Hash msg \<comment> \<open>Hashing\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 66 | | MPair msg msg \<comment> \<open>Compound messages\<close> | 
| 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 67 | | Crypt key msg \<comment> \<open>Encryption, public- or shared-key\<close> | 
| 14199 | 68 | |
| 69 | ||
| 61984 | 70 | (*Concrete syntax: messages appear as \<open>\<lbrace>A,B,NA\<rbrace>\<close>, etc...*) | 
| 14199 | 71 | syntax | 
| 67613 | 72 |   "_MTuple"      :: "['a, args] \<Rightarrow> 'a * 'b"       ("(2\<lbrace>_,/ _\<rbrace>)")
 | 
| 14199 | 73 | translations | 
| 61984 | 74 | "\<lbrace>x, y, z\<rbrace>" == "\<lbrace>x, \<lbrace>y, z\<rbrace>\<rbrace>" | 
| 75 | "\<lbrace>x, y\<rbrace>" == "CONST MPair x y" | |
| 14199 | 76 | |
| 77 | ||
| 67613 | 78 | definition nat_of_agent :: "agent \<Rightarrow> nat" where | 
| 55416 | 79 | "nat_of_agent == case_agent (curry prod_encode 0) | 
| 35703 
29cb504abbb5
convert SET_Protocol to use Nat_Bijection library
 huffman parents: 
35416diff
changeset | 80 | (curry prod_encode 1) | 
| 
29cb504abbb5
convert SET_Protocol to use Nat_Bijection library
 huffman parents: 
35416diff
changeset | 81 | (curry prod_encode 2) | 
| 
29cb504abbb5
convert SET_Protocol to use Nat_Bijection library
 huffman parents: 
35416diff
changeset | 82 | (curry prod_encode 3) | 
| 
29cb504abbb5
convert SET_Protocol to use Nat_Bijection library
 huffman parents: 
35416diff
changeset | 83 | (prod_encode (4,0))" | 
| 67443 
3abf6a722518
standardized towards new-style formal comments: isabelle update_comments;
 wenzelm parents: 
66453diff
changeset | 84 | \<comment> \<open>maps each agent to a unique natural number, for specifications\<close> | 
| 14199 | 85 | |
| 63167 | 86 | text\<open>The function is indeed injective\<close> | 
| 14199 | 87 | lemma inj_nat_of_agent: "inj nat_of_agent" | 
| 35703 
29cb504abbb5
convert SET_Protocol to use Nat_Bijection library
 huffman parents: 
35416diff
changeset | 88 | by (simp add: nat_of_agent_def inj_on_def curry_def prod_encode_eq split: agent.split) | 
| 14199 | 89 | |
| 90 | ||
| 36866 | 91 | definition | 
| 14199 | 92 | (*Keys useful to decrypt elements of a message set*) | 
| 67613 | 93 | keysFor :: "msg set \<Rightarrow> key set" | 
| 36866 | 94 |   where "keysFor H = invKey ` {K. \<exists>X. Crypt K X \<in> H}"
 | 
| 14199 | 95 | |
| 63167 | 96 | subsubsection\<open>Inductive definition of all "parts" of a message.\<close> | 
| 14199 | 97 | |
| 23755 | 98 | inductive_set | 
| 67613 | 99 | parts :: "msg set \<Rightarrow> msg set" | 
| 23755 | 100 | for H :: "msg set" | 
| 101 | where | |
| 14199 | 102 | Inj [intro]: "X \<in> H ==> X \<in> parts H" | 
| 61984 | 103 | | Fst: "\<lbrace>X,Y\<rbrace> \<in> parts H ==> X \<in> parts H" | 
| 104 | | Snd: "\<lbrace>X,Y\<rbrace> \<in> parts H ==> Y \<in> parts H" | |
| 23755 | 105 | | Body: "Crypt K X \<in> parts H ==> X \<in> parts H" | 
| 14199 | 106 | |
| 107 | ||
| 108 | (*Monotonicity*) | |
| 67613 | 109 | lemma parts_mono: "G\<subseteq>H ==> parts(G) \<subseteq> parts(H)" | 
| 14199 | 110 | apply auto | 
| 111 | apply (erule parts.induct) | |
| 112 | apply (auto dest: Fst Snd Body) | |
| 113 | done | |
| 114 | ||
| 115 | ||
| 63167 | 116 | subsubsection\<open>Inverse of keys\<close> | 
| 14199 | 117 | |
| 118 | (*Equations hold because constructors are injective; cannot prove for all f*) | |
| 119 | lemma Key_image_eq [simp]: "(Key x \<in> Key`A) = (x\<in>A)" | |
| 120 | by auto | |
| 121 | ||
| 122 | lemma Nonce_Key_image_eq [simp]: "(Nonce x \<notin> Key`A)" | |
| 123 | by auto | |
| 124 | ||
| 125 | lemma Cardholder_image_eq [simp]: "(Cardholder x \<in> Cardholder`A) = (x \<in> A)" | |
| 126 | by auto | |
| 127 | ||
| 128 | lemma CA_image_eq [simp]: "(CA x \<in> CA`A) = (x \<in> A)" | |
| 129 | by auto | |
| 130 | ||
| 131 | lemma Pan_image_eq [simp]: "(Pan x \<in> Pan`A) = (x \<in> A)" | |
| 132 | by auto | |
| 133 | ||
| 134 | lemma Pan_Key_image_eq [simp]: "(Pan x \<notin> Key`A)" | |
| 135 | by auto | |
| 136 | ||
| 137 | lemma Nonce_Pan_image_eq [simp]: "(Nonce x \<notin> Pan`A)" | |
| 138 | by auto | |
| 139 | ||
| 140 | lemma invKey_eq [simp]: "(invKey K = invKey K') = (K=K')" | |
| 141 | apply safe | |
| 142 | apply (drule_tac f = invKey in arg_cong, simp) | |
| 143 | done | |
| 144 | ||
| 145 | ||
| 63167 | 146 | subsection\<open>keysFor operator\<close> | 
| 14199 | 147 | |
| 148 | lemma keysFor_empty [simp]: "keysFor {} = {}"
 | |
| 149 | by (unfold keysFor_def, blast) | |
| 150 | ||
| 151 | lemma keysFor_Un [simp]: "keysFor (H \<union> H') = keysFor H \<union> keysFor H'" | |
| 152 | by (unfold keysFor_def, blast) | |
| 153 | ||
| 154 | lemma keysFor_UN [simp]: "keysFor (\<Union>i\<in>A. H i) = (\<Union>i\<in>A. keysFor (H i))" | |
| 155 | by (unfold keysFor_def, blast) | |
| 156 | ||
| 157 | (*Monotonicity*) | |
| 158 | lemma keysFor_mono: "G\<subseteq>H ==> keysFor(G) \<subseteq> keysFor(H)" | |
| 159 | by (unfold keysFor_def, blast) | |
| 160 | ||
| 161 | lemma keysFor_insert_Agent [simp]: "keysFor (insert (Agent A) H) = keysFor H" | |
| 162 | by (unfold keysFor_def, auto) | |
| 163 | ||
| 164 | lemma keysFor_insert_Nonce [simp]: "keysFor (insert (Nonce N) H) = keysFor H" | |
| 165 | by (unfold keysFor_def, auto) | |
| 166 | ||
| 167 | lemma keysFor_insert_Number [simp]: "keysFor (insert (Number N) H) = keysFor H" | |
| 168 | by (unfold keysFor_def, auto) | |
| 169 | ||
| 170 | lemma keysFor_insert_Key [simp]: "keysFor (insert (Key K) H) = keysFor H" | |
| 171 | by (unfold keysFor_def, auto) | |
| 172 | ||
| 173 | lemma keysFor_insert_Pan [simp]: "keysFor (insert (Pan A) H) = keysFor H" | |
| 174 | by (unfold keysFor_def, auto) | |
| 175 | ||
| 176 | lemma keysFor_insert_Hash [simp]: "keysFor (insert (Hash X) H) = keysFor H" | |
| 177 | by (unfold keysFor_def, auto) | |
| 178 | ||
| 61984 | 179 | lemma keysFor_insert_MPair [simp]: "keysFor (insert \<lbrace>X,Y\<rbrace> H) = keysFor H" | 
| 14199 | 180 | by (unfold keysFor_def, auto) | 
| 181 | ||
| 182 | lemma keysFor_insert_Crypt [simp]: | |
| 183 | "keysFor (insert (Crypt K X) H) = insert (invKey K) (keysFor H)" | |
| 184 | by (unfold keysFor_def, auto) | |
| 185 | ||
| 186 | lemma keysFor_image_Key [simp]: "keysFor (Key`E) = {}"
 | |
| 187 | by (unfold keysFor_def, auto) | |
| 188 | ||
| 189 | lemma Crypt_imp_invKey_keysFor: "Crypt K X \<in> H ==> invKey K \<in> keysFor H" | |
| 190 | by (unfold keysFor_def, blast) | |
| 191 | ||
| 192 | ||
| 63167 | 193 | subsection\<open>Inductive relation "parts"\<close> | 
| 14199 | 194 | |
| 195 | lemma MPair_parts: | |
| 61984 | 196 | "[| \<lbrace>X,Y\<rbrace> \<in> parts H; | 
| 14199 | 197 | [| X \<in> parts H; Y \<in> parts H |] ==> P |] ==> P" | 
| 198 | by (blast dest: parts.Fst parts.Snd) | |
| 199 | ||
| 200 | declare MPair_parts [elim!] parts.Body [dest!] | |
| 63167 | 201 | text\<open>NB These two rules are UNSAFE in the formal sense, as they discard the | 
| 14199 | 202 | compound message. They work well on THIS FILE. | 
| 63167 | 203 | \<open>MPair_parts\<close> is left as SAFE because it speeds up proofs. | 
| 204 | The Crypt rule is normally kept UNSAFE to avoid breaking up certificates.\<close> | |
| 14199 | 205 | |
| 206 | lemma parts_increasing: "H \<subseteq> parts(H)" | |
| 207 | by blast | |
| 208 | ||
| 45605 | 209 | lemmas parts_insertI = subset_insertI [THEN parts_mono, THEN subsetD] | 
| 14199 | 210 | |
| 211 | lemma parts_empty [simp]: "parts{} = {}"
 | |
| 212 | apply safe | |
| 213 | apply (erule parts.induct, blast+) | |
| 214 | done | |
| 215 | ||
| 216 | lemma parts_emptyE [elim!]: "X\<in> parts{} ==> P"
 | |
| 217 | by simp | |
| 218 | ||
| 219 | (*WARNING: loops if H = {Y}, therefore must not be repeated!*)
 | |
| 220 | lemma parts_singleton: "X\<in> parts H ==> \<exists>Y\<in>H. X\<in> parts {Y}"
 | |
| 26807 
4cd176ea28dc
Replaced blast by fast in proof of parts_singleton, since blast looped
 berghofe parents: 
26342diff
changeset | 221 | by (erule parts.induct, fast+) | 
| 14199 | 222 | |
| 223 | ||
| 63167 | 224 | subsubsection\<open>Unions\<close> | 
| 14199 | 225 | |
| 226 | lemma parts_Un_subset1: "parts(G) \<union> parts(H) \<subseteq> parts(G \<union> H)" | |
| 227 | by (intro Un_least parts_mono Un_upper1 Un_upper2) | |
| 228 | ||
| 229 | lemma parts_Un_subset2: "parts(G \<union> H) \<subseteq> parts(G) \<union> parts(H)" | |
| 230 | apply (rule subsetI) | |
| 231 | apply (erule parts.induct, blast+) | |
| 232 | done | |
| 233 | ||
| 234 | lemma parts_Un [simp]: "parts(G \<union> H) = parts(G) \<union> parts(H)" | |
| 235 | by (intro equalityI parts_Un_subset1 parts_Un_subset2) | |
| 236 | ||
| 237 | lemma parts_insert: "parts (insert X H) = parts {X} \<union> parts H"
 | |
| 238 | apply (subst insert_is_Un [of _ H]) | |
| 239 | apply (simp only: parts_Un) | |
| 240 | done | |
| 241 | ||
| 242 | (*TWO inserts to avoid looping. This rewrite is better than nothing. | |
| 243 | Not suitable for Addsimps: its behaviour can be strange.*) | |
| 244 | lemma parts_insert2: | |
| 245 |      "parts (insert X (insert Y H)) = parts {X} \<union> parts {Y} \<union> parts H"
 | |
| 246 | apply (simp add: Un_assoc) | |
| 247 | apply (simp add: parts_insert [symmetric]) | |
| 248 | done | |
| 249 | ||
| 250 | lemma parts_UN_subset1: "(\<Union>x\<in>A. parts(H x)) \<subseteq> parts(\<Union>x\<in>A. H x)" | |
| 251 | by (intro UN_least parts_mono UN_upper) | |
| 252 | ||
| 253 | lemma parts_UN_subset2: "parts(\<Union>x\<in>A. H x) \<subseteq> (\<Union>x\<in>A. parts(H x))" | |
| 254 | apply (rule subsetI) | |
| 255 | apply (erule parts.induct, blast+) | |
| 256 | done | |
| 257 | ||
| 258 | lemma parts_UN [simp]: "parts(\<Union>x\<in>A. H x) = (\<Union>x\<in>A. parts(H x))" | |
| 259 | by (intro equalityI parts_UN_subset1 parts_UN_subset2) | |
| 260 | ||
| 261 | (*Added to simplify arguments to parts, analz and synth. | |
| 262 | NOTE: the UN versions are no longer used!*) | |
| 263 | ||
| 264 | ||
| 63167 | 265 | text\<open>This allows \<open>blast\<close> to simplify occurrences of | 
| 69597 | 266 | \<^term>\<open>parts(G\<union>H)\<close> in the assumption.\<close> | 
| 14199 | 267 | declare parts_Un [THEN equalityD1, THEN subsetD, THEN UnE, elim!] | 
| 268 | ||
| 269 | ||
| 270 | lemma parts_insert_subset: "insert X (parts H) \<subseteq> parts(insert X H)" | |
| 271 | by (blast intro: parts_mono [THEN [2] rev_subsetD]) | |
| 272 | ||
| 63167 | 273 | subsubsection\<open>Idempotence and transitivity\<close> | 
| 14199 | 274 | |
| 275 | lemma parts_partsD [dest!]: "X\<in> parts (parts H) ==> X\<in> parts H" | |
| 276 | by (erule parts.induct, blast+) | |
| 277 | ||
| 278 | lemma parts_idem [simp]: "parts (parts H) = parts H" | |
| 279 | by blast | |
| 280 | ||
| 281 | lemma parts_trans: "[| X\<in> parts G; G \<subseteq> parts H |] ==> X\<in> parts H" | |
| 282 | by (drule parts_mono, blast) | |
| 283 | ||
| 284 | (*Cut*) | |
| 285 | lemma parts_cut: | |
| 286 | "[| Y\<in> parts (insert X G); X\<in> parts H |] ==> Y\<in> parts (G \<union> H)" | |
| 287 | by (erule parts_trans, auto) | |
| 288 | ||
| 289 | lemma parts_cut_eq [simp]: "X\<in> parts H ==> parts (insert X H) = parts H" | |
| 290 | by (force dest!: parts_cut intro: parts_insertI) | |
| 291 | ||
| 292 | ||
| 63167 | 293 | subsubsection\<open>Rewrite rules for pulling out atomic messages\<close> | 
| 14199 | 294 | |
| 295 | lemmas parts_insert_eq_I = equalityI [OF subsetI parts_insert_subset] | |
| 296 | ||
| 297 | ||
| 298 | lemma parts_insert_Agent [simp]: | |
| 299 | "parts (insert (Agent agt) H) = insert (Agent agt) (parts H)" | |
| 300 | apply (rule parts_insert_eq_I) | |
| 301 | apply (erule parts.induct, auto) | |
| 302 | done | |
| 303 | ||
| 304 | lemma parts_insert_Nonce [simp]: | |
| 305 | "parts (insert (Nonce N) H) = insert (Nonce N) (parts H)" | |
| 306 | apply (rule parts_insert_eq_I) | |
| 307 | apply (erule parts.induct, auto) | |
| 308 | done | |
| 309 | ||
| 310 | lemma parts_insert_Number [simp]: | |
| 311 | "parts (insert (Number N) H) = insert (Number N) (parts H)" | |
| 312 | apply (rule parts_insert_eq_I) | |
| 313 | apply (erule parts.induct, auto) | |
| 314 | done | |
| 315 | ||
| 316 | lemma parts_insert_Key [simp]: | |
| 317 | "parts (insert (Key K) H) = insert (Key K) (parts H)" | |
| 318 | apply (rule parts_insert_eq_I) | |
| 319 | apply (erule parts.induct, auto) | |
| 320 | done | |
| 321 | ||
| 322 | lemma parts_insert_Pan [simp]: | |
| 323 | "parts (insert (Pan A) H) = insert (Pan A) (parts H)" | |
| 324 | apply (rule parts_insert_eq_I) | |
| 325 | apply (erule parts.induct, auto) | |
| 326 | done | |
| 327 | ||
| 328 | lemma parts_insert_Hash [simp]: | |
| 329 | "parts (insert (Hash X) H) = insert (Hash X) (parts H)" | |
| 330 | apply (rule parts_insert_eq_I) | |
| 331 | apply (erule parts.induct, auto) | |
| 332 | done | |
| 333 | ||
| 334 | lemma parts_insert_Crypt [simp]: | |
| 335 | "parts (insert (Crypt K X) H) = | |
| 336 | insert (Crypt K X) (parts (insert X H))" | |
| 337 | apply (rule equalityI) | |
| 338 | apply (rule subsetI) | |
| 339 | apply (erule parts.induct, auto) | |
| 340 | apply (erule parts.induct) | |
| 341 | apply (blast intro: parts.Body)+ | |
| 342 | done | |
| 343 | ||
| 344 | lemma parts_insert_MPair [simp]: | |
| 61984 | 345 | "parts (insert \<lbrace>X,Y\<rbrace> H) = | 
| 346 | insert \<lbrace>X,Y\<rbrace> (parts (insert X (insert Y H)))" | |
| 14199 | 347 | apply (rule equalityI) | 
| 348 | apply (rule subsetI) | |
| 349 | apply (erule parts.induct, auto) | |
| 350 | apply (erule parts.induct) | |
| 351 | apply (blast intro: parts.Fst parts.Snd)+ | |
| 352 | done | |
| 353 | ||
| 354 | lemma parts_image_Key [simp]: "parts (Key`N) = Key`N" | |
| 355 | apply auto | |
| 356 | apply (erule parts.induct, auto) | |
| 357 | done | |
| 358 | ||
| 359 | lemma parts_image_Pan [simp]: "parts (Pan`A) = Pan`A" | |
| 360 | apply auto | |
| 361 | apply (erule parts.induct, auto) | |
| 362 | done | |
| 363 | ||
| 364 | ||
| 365 | (*In any message, there is an upper bound N on its greatest nonce.*) | |
| 67613 | 366 | lemma msg_Nonce_supply: "\<exists>N. \<forall>n. N\<le>n \<longrightarrow> Nonce n \<notin> parts {msg}"
 | 
| 14199 | 367 | apply (induct_tac "msg") | 
| 368 | apply (simp_all (no_asm_simp) add: exI parts_insert2) | |
| 369 | (*MPair case: blast_tac works out the necessary sum itself!*) | |
| 370 | prefer 2 apply (blast elim!: add_leE) | |
| 371 | (*Nonce case*) | |
| 58305 
57752a91eec4
renamed 'datatype' to 'old_datatype'; 'datatype' is now alias for 'datatype_new'
 blanchet parents: 
55416diff
changeset | 372 | apply (rename_tac nat) | 
| 14199 | 373 | apply (rule_tac x = "N + Suc nat" in exI) | 
| 374 | apply (auto elim!: add_leE) | |
| 375 | done | |
| 376 | ||
| 377 | (* Ditto, for numbers.*) | |
| 67613 | 378 | lemma msg_Number_supply: "\<exists>N. \<forall>n. N\<le>n \<longrightarrow> Number n \<notin> parts {msg}"
 | 
| 14199 | 379 | apply (induct_tac "msg") | 
| 380 | apply (simp_all (no_asm_simp) add: exI parts_insert2) | |
| 381 | prefer 2 apply (blast elim!: add_leE) | |
| 58305 
57752a91eec4
renamed 'datatype' to 'old_datatype'; 'datatype' is now alias for 'datatype_new'
 blanchet parents: 
55416diff
changeset | 382 | apply (rename_tac nat) | 
| 14199 | 383 | apply (rule_tac x = "N + Suc nat" in exI, auto) | 
| 384 | done | |
| 385 | ||
| 63167 | 386 | subsection\<open>Inductive relation "analz"\<close> | 
| 14199 | 387 | |
| 63167 | 388 | text\<open>Inductive definition of "analz" -- what can be broken down from a set of | 
| 14199 | 389 | messages, including keys. A form of downward closure. Pairs can | 
| 63167 | 390 | be taken apart; messages decrypted with known keys.\<close> | 
| 14199 | 391 | |
| 23755 | 392 | inductive_set | 
| 393 | analz :: "msg set => msg set" | |
| 394 | for H :: "msg set" | |
| 395 | where | |
| 14199 | 396 | Inj [intro,simp] : "X \<in> H ==> X \<in> analz H" | 
| 61984 | 397 | | Fst: "\<lbrace>X,Y\<rbrace> \<in> analz H ==> X \<in> analz H" | 
| 398 | | Snd: "\<lbrace>X,Y\<rbrace> \<in> analz H ==> Y \<in> analz H" | |
| 23755 | 399 | | Decrypt [dest]: | 
| 67613 | 400 | "[|Crypt K X \<in> analz H; Key(invKey K) \<in> analz H|] ==> X \<in> analz H" | 
| 14199 | 401 | |
| 402 | ||
| 403 | (*Monotonicity; Lemma 1 of Lowe's paper*) | |
| 67613 | 404 | lemma analz_mono: "G\<subseteq>H ==> analz(G) \<subseteq> analz(H)" | 
| 14199 | 405 | apply auto | 
| 406 | apply (erule analz.induct) | |
| 407 | apply (auto dest: Fst Snd) | |
| 408 | done | |
| 409 | ||
| 63167 | 410 | text\<open>Making it safe speeds up proofs\<close> | 
| 14199 | 411 | lemma MPair_analz [elim!]: | 
| 61984 | 412 | "[| \<lbrace>X,Y\<rbrace> \<in> analz H; | 
| 14199 | 413 | [| X \<in> analz H; Y \<in> analz H |] ==> P | 
| 414 | |] ==> P" | |
| 415 | by (blast dest: analz.Fst analz.Snd) | |
| 416 | ||
| 417 | lemma analz_increasing: "H \<subseteq> analz(H)" | |
| 418 | by blast | |
| 419 | ||
| 420 | lemma analz_subset_parts: "analz H \<subseteq> parts H" | |
| 421 | apply (rule subsetI) | |
| 422 | apply (erule analz.induct, blast+) | |
| 423 | done | |
| 424 | ||
| 45605 | 425 | lemmas analz_into_parts = analz_subset_parts [THEN subsetD] | 
| 14199 | 426 | |
| 45605 | 427 | lemmas not_parts_not_analz = analz_subset_parts [THEN contra_subsetD] | 
| 14199 | 428 | |
| 429 | ||
| 430 | lemma parts_analz [simp]: "parts (analz H) = parts H" | |
| 431 | apply (rule equalityI) | |
| 432 | apply (rule analz_subset_parts [THEN parts_mono, THEN subset_trans], simp) | |
| 433 | apply (blast intro: analz_increasing [THEN parts_mono, THEN subsetD]) | |
| 434 | done | |
| 435 | ||
| 436 | lemma analz_parts [simp]: "analz (parts H) = parts H" | |
| 437 | apply auto | |
| 438 | apply (erule analz.induct, auto) | |
| 439 | done | |
| 440 | ||
| 45605 | 441 | lemmas analz_insertI = subset_insertI [THEN analz_mono, THEN [2] rev_subsetD] | 
| 14199 | 442 | |
| 63167 | 443 | subsubsection\<open>General equational properties\<close> | 
| 14199 | 444 | |
| 445 | lemma analz_empty [simp]: "analz{} = {}"
 | |
| 446 | apply safe | |
| 447 | apply (erule analz.induct, blast+) | |
| 448 | done | |
| 449 | ||
| 450 | (*Converse fails: we can analz more from the union than from the | |
| 451 | separate parts, as a key in one might decrypt a message in the other*) | |
| 452 | lemma analz_Un: "analz(G) \<union> analz(H) \<subseteq> analz(G \<union> H)" | |
| 453 | by (intro Un_least analz_mono Un_upper1 Un_upper2) | |
| 454 | ||
| 455 | lemma analz_insert: "insert X (analz H) \<subseteq> analz(insert X H)" | |
| 456 | by (blast intro: analz_mono [THEN [2] rev_subsetD]) | |
| 457 | ||
| 63167 | 458 | subsubsection\<open>Rewrite rules for pulling out atomic messages\<close> | 
| 14199 | 459 | |
| 460 | lemmas analz_insert_eq_I = equalityI [OF subsetI analz_insert] | |
| 461 | ||
| 462 | lemma analz_insert_Agent [simp]: | |
| 463 | "analz (insert (Agent agt) H) = insert (Agent agt) (analz H)" | |
| 464 | apply (rule analz_insert_eq_I) | |
| 465 | apply (erule analz.induct, auto) | |
| 466 | done | |
| 467 | ||
| 468 | lemma analz_insert_Nonce [simp]: | |
| 469 | "analz (insert (Nonce N) H) = insert (Nonce N) (analz H)" | |
| 470 | apply (rule analz_insert_eq_I) | |
| 471 | apply (erule analz.induct, auto) | |
| 472 | done | |
| 473 | ||
| 474 | lemma analz_insert_Number [simp]: | |
| 475 | "analz (insert (Number N) H) = insert (Number N) (analz H)" | |
| 476 | apply (rule analz_insert_eq_I) | |
| 477 | apply (erule analz.induct, auto) | |
| 478 | done | |
| 479 | ||
| 480 | lemma analz_insert_Hash [simp]: | |
| 481 | "analz (insert (Hash X) H) = insert (Hash X) (analz H)" | |
| 482 | apply (rule analz_insert_eq_I) | |
| 483 | apply (erule analz.induct, auto) | |
| 484 | done | |
| 485 | ||
| 486 | (*Can only pull out Keys if they are not needed to decrypt the rest*) | |
| 487 | lemma analz_insert_Key [simp]: | |
| 488 | "K \<notin> keysFor (analz H) ==> | |
| 489 | analz (insert (Key K) H) = insert (Key K) (analz H)" | |
| 490 | apply (unfold keysFor_def) | |
| 491 | apply (rule analz_insert_eq_I) | |
| 492 | apply (erule analz.induct, auto) | |
| 493 | done | |
| 494 | ||
| 495 | lemma analz_insert_MPair [simp]: | |
| 61984 | 496 | "analz (insert \<lbrace>X,Y\<rbrace> H) = | 
| 497 | insert \<lbrace>X,Y\<rbrace> (analz (insert X (insert Y H)))" | |
| 14199 | 498 | apply (rule equalityI) | 
| 499 | apply (rule subsetI) | |
| 500 | apply (erule analz.induct, auto) | |
| 501 | apply (erule analz.induct) | |
| 502 | apply (blast intro: analz.Fst analz.Snd)+ | |
| 503 | done | |
| 504 | ||
| 505 | (*Can pull out enCrypted message if the Key is not known*) | |
| 506 | lemma analz_insert_Crypt: | |
| 507 | "Key (invKey K) \<notin> analz H | |
| 508 | ==> analz (insert (Crypt K X) H) = insert (Crypt K X) (analz H)" | |
| 509 | apply (rule analz_insert_eq_I) | |
| 510 | apply (erule analz.induct, auto) | |
| 511 | done | |
| 512 | ||
| 513 | lemma analz_insert_Pan [simp]: | |
| 514 | "analz (insert (Pan A) H) = insert (Pan A) (analz H)" | |
| 515 | apply (rule analz_insert_eq_I) | |
| 516 | apply (erule analz.induct, auto) | |
| 517 | done | |
| 518 | ||
| 519 | lemma lemma1: "Key (invKey K) \<in> analz H ==> | |
| 520 | analz (insert (Crypt K X) H) \<subseteq> | |
| 521 | insert (Crypt K X) (analz (insert X H))" | |
| 522 | apply (rule subsetI) | |
| 23755 | 523 | apply (erule_tac x = x in analz.induct, auto) | 
| 14199 | 524 | done | 
| 525 | ||
| 526 | lemma lemma2: "Key (invKey K) \<in> analz H ==> | |
| 527 | insert (Crypt K X) (analz (insert X H)) \<subseteq> | |
| 528 | analz (insert (Crypt K X) H)" | |
| 529 | apply auto | |
| 23755 | 530 | apply (erule_tac x = x in analz.induct, auto) | 
| 14199 | 531 | apply (blast intro: analz_insertI analz.Decrypt) | 
| 532 | done | |
| 533 | ||
| 534 | lemma analz_insert_Decrypt: | |
| 535 | "Key (invKey K) \<in> analz H ==> | |
| 536 | analz (insert (Crypt K X) H) = | |
| 537 | insert (Crypt K X) (analz (insert X H))" | |
| 538 | by (intro equalityI lemma1 lemma2) | |
| 539 | ||
| 540 | (*Case analysis: either the message is secure, or it is not! | |
| 541 | Effective, but can cause subgoals to blow up! | |
| 62390 | 542 | Use with if_split; apparently split_tac does not cope with patterns | 
| 14199 | 543 | such as "analz (insert (Crypt K X) H)" *) | 
| 544 | lemma analz_Crypt_if [simp]: | |
| 545 | "analz (insert (Crypt K X) H) = | |
| 546 | (if (Key (invKey K) \<in> analz H) | |
| 547 | then insert (Crypt K X) (analz (insert X H)) | |
| 548 | else insert (Crypt K X) (analz H))" | |
| 549 | by (simp add: analz_insert_Crypt analz_insert_Decrypt) | |
| 550 | ||
| 551 | ||
| 552 | (*This rule supposes "for the sake of argument" that we have the key.*) | |
| 553 | lemma analz_insert_Crypt_subset: | |
| 554 | "analz (insert (Crypt K X) H) \<subseteq> | |
| 555 | insert (Crypt K X) (analz (insert X H))" | |
| 556 | apply (rule subsetI) | |
| 557 | apply (erule analz.induct, auto) | |
| 558 | done | |
| 559 | ||
| 560 | lemma analz_image_Key [simp]: "analz (Key`N) = Key`N" | |
| 561 | apply auto | |
| 562 | apply (erule analz.induct, auto) | |
| 563 | done | |
| 564 | ||
| 565 | lemma analz_image_Pan [simp]: "analz (Pan`A) = Pan`A" | |
| 566 | apply auto | |
| 567 | apply (erule analz.induct, auto) | |
| 568 | done | |
| 569 | ||
| 570 | ||
| 63167 | 571 | subsubsection\<open>Idempotence and transitivity\<close> | 
| 14199 | 572 | |
| 573 | lemma analz_analzD [dest!]: "X\<in> analz (analz H) ==> X\<in> analz H" | |
| 574 | by (erule analz.induct, blast+) | |
| 575 | ||
| 576 | lemma analz_idem [simp]: "analz (analz H) = analz H" | |
| 577 | by blast | |
| 578 | ||
| 579 | lemma analz_trans: "[| X\<in> analz G; G \<subseteq> analz H |] ==> X\<in> analz H" | |
| 580 | by (drule analz_mono, blast) | |
| 581 | ||
| 582 | (*Cut; Lemma 2 of Lowe*) | |
| 583 | lemma analz_cut: "[| Y\<in> analz (insert X H); X\<in> analz H |] ==> Y\<in> analz H" | |
| 584 | by (erule analz_trans, blast) | |
| 585 | ||
| 586 | (*Cut can be proved easily by induction on | |
| 67613 | 587 | "Y: analz (insert X H) ==> X: analz H \<longrightarrow> Y: analz H" | 
| 14199 | 588 | *) | 
| 589 | ||
| 590 | (*This rewrite rule helps in the simplification of messages that involve | |
| 591 | the forwarding of unknown components (X). Without it, removing occurrences | |
| 592 | of X can be very complicated. *) | |
| 593 | lemma analz_insert_eq: "X\<in> analz H ==> analz (insert X H) = analz H" | |
| 594 | by (blast intro: analz_cut analz_insertI) | |
| 595 | ||
| 596 | ||
| 63167 | 597 | text\<open>A congruence rule for "analz"\<close> | 
| 14199 | 598 | |
| 599 | lemma analz_subset_cong: | |
| 600 | "[| analz G \<subseteq> analz G'; analz H \<subseteq> analz H' | |
| 601 | |] ==> analz (G \<union> H) \<subseteq> analz (G' \<union> H')" | |
| 602 | apply clarify | |
| 603 | apply (erule analz.induct) | |
| 604 | apply (best intro: analz_mono [THEN subsetD])+ | |
| 605 | done | |
| 606 | ||
| 607 | lemma analz_cong: | |
| 608 | "[| analz G = analz G'; analz H = analz H' | |
| 609 | |] ==> analz (G \<union> H) = analz (G' \<union> H')" | |
| 610 | by (intro equalityI analz_subset_cong, simp_all) | |
| 611 | ||
| 612 | lemma analz_insert_cong: | |
| 613 | "analz H = analz H' ==> analz(insert X H) = analz(insert X H')" | |
| 614 | by (force simp only: insert_def intro!: analz_cong) | |
| 615 | ||
| 616 | (*If there are no pairs or encryptions then analz does nothing*) | |
| 617 | lemma analz_trivial: | |
| 61984 | 618 | "[| \<forall>X Y. \<lbrace>X,Y\<rbrace> \<notin> H; \<forall>X K. Crypt K X \<notin> H |] ==> analz H = H" | 
| 14199 | 619 | apply safe | 
| 620 | apply (erule analz.induct, blast+) | |
| 621 | done | |
| 622 | ||
| 623 | (*These two are obsolete (with a single Spy) but cost little to prove...*) | |
| 624 | lemma analz_UN_analz_lemma: | |
| 625 | "X\<in> analz (\<Union>i\<in>A. analz (H i)) ==> X\<in> analz (\<Union>i\<in>A. H i)" | |
| 626 | apply (erule analz.induct) | |
| 627 | apply (blast intro: analz_mono [THEN [2] rev_subsetD])+ | |
| 628 | done | |
| 629 | ||
| 630 | lemma analz_UN_analz [simp]: "analz (\<Union>i\<in>A. analz (H i)) = analz (\<Union>i\<in>A. H i)" | |
| 631 | by (blast intro: analz_UN_analz_lemma analz_mono [THEN [2] rev_subsetD]) | |
| 632 | ||
| 633 | ||
| 63167 | 634 | subsection\<open>Inductive relation "synth"\<close> | 
| 14199 | 635 | |
| 63167 | 636 | text\<open>Inductive definition of "synth" -- what can be built up from a set of | 
| 14199 | 637 | messages. A form of upward closure. Pairs can be built, messages | 
| 638 | encrypted with known keys. Agent names are public domain. | |
| 63167 | 639 | Numbers can be guessed, but Nonces cannot be.\<close> | 
| 14199 | 640 | |
| 23755 | 641 | inductive_set | 
| 67613 | 642 | synth :: "msg set \<Rightarrow> msg set" | 
| 23755 | 643 | for H :: "msg set" | 
| 644 | where | |
| 14199 | 645 | Inj [intro]: "X \<in> H ==> X \<in> synth H" | 
| 23755 | 646 | | Agent [intro]: "Agent agt \<in> synth H" | 
| 647 | | Number [intro]: "Number n \<in> synth H" | |
| 648 | | Hash [intro]: "X \<in> synth H ==> Hash X \<in> synth H" | |
| 61984 | 649 | | MPair [intro]: "[|X \<in> synth H; Y \<in> synth H|] ==> \<lbrace>X,Y\<rbrace> \<in> synth H" | 
| 23755 | 650 | | Crypt [intro]: "[|X \<in> synth H; Key(K) \<in> H|] ==> Crypt K X \<in> synth H" | 
| 14199 | 651 | |
| 652 | (*Monotonicity*) | |
| 67613 | 653 | lemma synth_mono: "G\<subseteq>H ==> synth(G) \<subseteq> synth(H)" | 
| 14199 | 654 | apply auto | 
| 655 | apply (erule synth.induct) | |
| 656 | apply (auto dest: Fst Snd Body) | |
| 657 | done | |
| 658 | ||
| 659 | (*NO Agent_synth, as any Agent name can be synthesized. Ditto for Number*) | |
| 660 | inductive_cases Nonce_synth [elim!]: "Nonce n \<in> synth H" | |
| 661 | inductive_cases Key_synth [elim!]: "Key K \<in> synth H" | |
| 662 | inductive_cases Hash_synth [elim!]: "Hash X \<in> synth H" | |
| 61984 | 663 | inductive_cases MPair_synth [elim!]: "\<lbrace>X,Y\<rbrace> \<in> synth H" | 
| 14199 | 664 | inductive_cases Crypt_synth [elim!]: "Crypt K X \<in> synth H" | 
| 665 | inductive_cases Pan_synth [elim!]: "Pan A \<in> synth H" | |
| 666 | ||
| 667 | ||
| 668 | lemma synth_increasing: "H \<subseteq> synth(H)" | |
| 669 | by blast | |
| 670 | ||
| 63167 | 671 | subsubsection\<open>Unions\<close> | 
| 14199 | 672 | |
| 673 | (*Converse fails: we can synth more from the union than from the | |
| 674 | separate parts, building a compound message using elements of each.*) | |
| 675 | lemma synth_Un: "synth(G) \<union> synth(H) \<subseteq> synth(G \<union> H)" | |
| 676 | by (intro Un_least synth_mono Un_upper1 Un_upper2) | |
| 677 | ||
| 678 | lemma synth_insert: "insert X (synth H) \<subseteq> synth(insert X H)" | |
| 679 | by (blast intro: synth_mono [THEN [2] rev_subsetD]) | |
| 680 | ||
| 63167 | 681 | subsubsection\<open>Idempotence and transitivity\<close> | 
| 14199 | 682 | |
| 683 | lemma synth_synthD [dest!]: "X\<in> synth (synth H) ==> X\<in> synth H" | |
| 684 | by (erule synth.induct, blast+) | |
| 685 | ||
| 686 | lemma synth_idem: "synth (synth H) = synth H" | |
| 687 | by blast | |
| 688 | ||
| 689 | lemma synth_trans: "[| X\<in> synth G; G \<subseteq> synth H |] ==> X\<in> synth H" | |
| 690 | by (drule synth_mono, blast) | |
| 691 | ||
| 692 | (*Cut; Lemma 2 of Lowe*) | |
| 693 | lemma synth_cut: "[| Y\<in> synth (insert X H); X\<in> synth H |] ==> Y\<in> synth H" | |
| 694 | by (erule synth_trans, blast) | |
| 695 | ||
| 696 | lemma Agent_synth [simp]: "Agent A \<in> synth H" | |
| 697 | by blast | |
| 698 | ||
| 699 | lemma Number_synth [simp]: "Number n \<in> synth H" | |
| 700 | by blast | |
| 701 | ||
| 702 | lemma Nonce_synth_eq [simp]: "(Nonce N \<in> synth H) = (Nonce N \<in> H)" | |
| 703 | by blast | |
| 704 | ||
| 705 | lemma Key_synth_eq [simp]: "(Key K \<in> synth H) = (Key K \<in> H)" | |
| 706 | by blast | |
| 707 | ||
| 708 | lemma Crypt_synth_eq [simp]: "Key K \<notin> H ==> (Crypt K X \<in> synth H) = (Crypt K X \<in> H)" | |
| 709 | by blast | |
| 710 | ||
| 711 | lemma Pan_synth_eq [simp]: "(Pan A \<in> synth H) = (Pan A \<in> H)" | |
| 712 | by blast | |
| 713 | ||
| 714 | lemma keysFor_synth [simp]: | |
| 715 |     "keysFor (synth H) = keysFor H \<union> invKey`{K. Key K \<in> H}"
 | |
| 716 | by (unfold keysFor_def, blast) | |
| 717 | ||
| 718 | ||
| 63167 | 719 | subsubsection\<open>Combinations of parts, analz and synth\<close> | 
| 14199 | 720 | |
| 721 | lemma parts_synth [simp]: "parts (synth H) = parts H \<union> synth H" | |
| 722 | apply (rule equalityI) | |
| 723 | apply (rule subsetI) | |
| 724 | apply (erule parts.induct) | |
| 725 | apply (blast intro: synth_increasing [THEN parts_mono, THEN subsetD] | |
| 726 | parts.Fst parts.Snd parts.Body)+ | |
| 727 | done | |
| 728 | ||
| 729 | lemma analz_analz_Un [simp]: "analz (analz G \<union> H) = analz (G \<union> H)" | |
| 730 | apply (intro equalityI analz_subset_cong)+ | |
| 731 | apply simp_all | |
| 732 | done | |
| 733 | ||
| 734 | lemma analz_synth_Un [simp]: "analz (synth G \<union> H) = analz (G \<union> H) \<union> synth G" | |
| 735 | apply (rule equalityI) | |
| 736 | apply (rule subsetI) | |
| 737 | apply (erule analz.induct) | |
| 738 | prefer 5 apply (blast intro: analz_mono [THEN [2] rev_subsetD]) | |
| 739 | apply (blast intro: analz.Fst analz.Snd analz.Decrypt)+ | |
| 740 | done | |
| 741 | ||
| 742 | lemma analz_synth [simp]: "analz (synth H) = analz H \<union> synth H" | |
| 743 | apply (cut_tac H = "{}" in analz_synth_Un)
 | |
| 744 | apply (simp (no_asm_use)) | |
| 745 | done | |
| 746 | ||
| 747 | ||
| 63167 | 748 | subsubsection\<open>For reasoning about the Fake rule in traces\<close> | 
| 14199 | 749 | |
| 750 | lemma parts_insert_subset_Un: "X\<in> G ==> parts(insert X H) \<subseteq> parts G \<union> parts H" | |
| 751 | by (rule subset_trans [OF parts_mono parts_Un_subset2], blast) | |
| 752 | ||
| 753 | (*More specifically for Fake. Very occasionally we could do with a version | |
| 754 |   of the form  parts{X} \<subseteq> synth (analz H) \<union> parts H *)
 | |
| 755 | lemma Fake_parts_insert: "X \<in> synth (analz H) ==> | |
| 756 | parts (insert X H) \<subseteq> synth (analz H) \<union> parts H" | |
| 757 | apply (drule parts_insert_subset_Un) | |
| 758 | apply (simp (no_asm_use)) | |
| 759 | apply blast | |
| 760 | done | |
| 761 | ||
| 762 | lemma Fake_parts_insert_in_Un: | |
| 67613 | 763 | "[|Z \<in> parts (insert X H); X \<in> synth (analz H)|] | 
| 58860 | 764 | ==> Z \<in> synth (analz H) \<union> parts H" | 
| 14199 | 765 | by (blast dest: Fake_parts_insert [THEN subsetD, dest]) | 
| 766 | ||
| 767 | (*H is sometimes (Key ` KK \<union> spies evs), so can't put G=H*) | |
| 768 | lemma Fake_analz_insert: | |
| 769 | "X\<in> synth (analz G) ==> | |
| 770 | analz (insert X H) \<subseteq> synth (analz G) \<union> analz (G \<union> H)" | |
| 771 | apply (rule subsetI) | |
| 772 | apply (subgoal_tac "x \<in> analz (synth (analz G) \<union> H) ") | |
| 773 | prefer 2 apply (blast intro: analz_mono [THEN [2] rev_subsetD] analz_mono [THEN synth_mono, THEN [2] rev_subsetD]) | |
| 774 | apply (simp (no_asm_use)) | |
| 775 | apply blast | |
| 776 | done | |
| 777 | ||
| 778 | lemma analz_conj_parts [simp]: | |
| 67613 | 779 | "(X \<in> analz H \<and> X \<in> parts H) = (X \<in> analz H)" | 
| 14199 | 780 | by (blast intro: analz_subset_parts [THEN subsetD]) | 
| 781 | ||
| 782 | lemma analz_disj_parts [simp]: | |
| 783 | "(X \<in> analz H | X \<in> parts H) = (X \<in> parts H)" | |
| 784 | by (blast intro: analz_subset_parts [THEN subsetD]) | |
| 785 | ||
| 786 | (*Without this equation, other rules for synth and analz would yield | |
| 787 | redundant cases*) | |
| 788 | lemma MPair_synth_analz [iff]: | |
| 61984 | 789 | "(\<lbrace>X,Y\<rbrace> \<in> synth (analz H)) = | 
| 67613 | 790 | (X \<in> synth (analz H) \<and> Y \<in> synth (analz H))" | 
| 14199 | 791 | by blast | 
| 792 | ||
| 793 | lemma Crypt_synth_analz: | |
| 794 | "[| Key K \<in> analz H; Key (invKey K) \<in> analz H |] | |
| 795 | ==> (Crypt K X \<in> synth (analz H)) = (X \<in> synth (analz H))" | |
| 796 | by blast | |
| 797 | ||
| 798 | ||
| 799 | lemma Hash_synth_analz [simp]: | |
| 800 | "X \<notin> synth (analz H) | |
| 61984 | 801 | ==> (Hash\<lbrace>X,Y\<rbrace> \<in> synth (analz H)) = (Hash\<lbrace>X,Y\<rbrace> \<in> analz H)" | 
| 14199 | 802 | by blast | 
| 803 | ||
| 804 | ||
| 805 | (*We do NOT want Crypt... messages broken up in protocols!!*) | |
| 806 | declare parts.Body [rule del] | |
| 807 | ||
| 808 | ||
| 63167 | 809 | text\<open>Rewrites to push in Key and Crypt messages, so that other messages can | 
| 810 | be pulled out using the \<open>analz_insert\<close> rules\<close> | |
| 14199 | 811 | |
| 45605 | 812 | lemmas pushKeys = | 
| 27225 | 813 | insert_commute [of "Key K" "Agent C"] | 
| 814 | insert_commute [of "Key K" "Nonce N"] | |
| 815 | insert_commute [of "Key K" "Number N"] | |
| 816 | insert_commute [of "Key K" "Pan PAN"] | |
| 817 | insert_commute [of "Key K" "Hash X"] | |
| 818 | insert_commute [of "Key K" "MPair X Y"] | |
| 819 | insert_commute [of "Key K" "Crypt X K'"] | |
| 45605 | 820 | for K C N PAN X Y K' | 
| 14199 | 821 | |
| 45605 | 822 | lemmas pushCrypts = | 
| 27225 | 823 | insert_commute [of "Crypt X K" "Agent C"] | 
| 824 | insert_commute [of "Crypt X K" "Nonce N"] | |
| 825 | insert_commute [of "Crypt X K" "Number N"] | |
| 826 | insert_commute [of "Crypt X K" "Pan PAN"] | |
| 827 | insert_commute [of "Crypt X K" "Hash X'"] | |
| 828 | insert_commute [of "Crypt X K" "MPair X' Y"] | |
| 45605 | 829 | for X K C N PAN X' Y | 
| 14199 | 830 | |
| 63167 | 831 | text\<open>Cannot be added with \<open>[simp]\<close> -- messages should not always be | 
| 832 | re-ordered.\<close> | |
| 14199 | 833 | lemmas pushes = pushKeys pushCrypts | 
| 834 | ||
| 835 | ||
| 63167 | 836 | subsection\<open>Tactics useful for many protocol proofs\<close> | 
| 14218 | 837 | (*<*) | 
| 14199 | 838 | ML | 
| 63167 | 839 | \<open> | 
| 14199 | 840 | (*Analysis of Fake cases. Also works for messages that forward unknown parts, | 
| 841 | but this application is no longer necessary if analz_insert_eq is used. | |
| 842 | DEPENDS UPON "X" REFERRING TO THE FRADULENT MESSAGE *) | |
| 843 | ||
| 32117 
0762b9ad83df
Set.thy: prefer = over == where possible; tuned ML setup; dropped (moved) ML legacy
 haftmann parents: 
30607diff
changeset | 844 | fun impOfSubs th = th RSN (2, @{thm rev_subsetD})
 | 
| 
0762b9ad83df
Set.thy: prefer = over == where possible; tuned ML setup; dropped (moved) ML legacy
 haftmann parents: 
30607diff
changeset | 845 | |
| 14199 | 846 | (*Apply rules to break down assumptions of the form | 
| 847 | Y \<in> parts(insert X H) and Y \<in> analz(insert X H) | |
| 848 | *) | |
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
58889diff
changeset | 849 | fun Fake_insert_tac ctxt = | 
| 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
58889diff
changeset | 850 |     dresolve_tac ctxt [impOfSubs @{thm Fake_analz_insert},
 | 
| 24123 | 851 |                   impOfSubs @{thm Fake_parts_insert}] THEN'
 | 
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
58889diff
changeset | 852 |     eresolve_tac ctxt [asm_rl, @{thm synth.Inj}];
 | 
| 14199 | 853 | |
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
51702diff
changeset | 854 | fun Fake_insert_simp_tac ctxt i = | 
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
58889diff
changeset | 855 | REPEAT (Fake_insert_tac ctxt i) THEN asm_full_simp_tac ctxt i; | 
| 14199 | 856 | |
| 42474 | 857 | fun atomic_spy_analz_tac ctxt = | 
| 42793 | 858 | SELECT_GOAL | 
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
51702diff
changeset | 859 | (Fake_insert_simp_tac ctxt 1 THEN | 
| 42793 | 860 | IF_UNSOLVED | 
| 861 |         (Blast.depth_tac (ctxt addIs [@{thm analz_insertI},
 | |
| 862 |             impOfSubs @{thm analz_subset_parts}]) 4 1));
 | |
| 14199 | 863 | |
| 42474 | 864 | fun spy_analz_tac ctxt i = | 
| 42793 | 865 | DETERM | 
| 866 | (SELECT_GOAL | |
| 867 | (EVERY | |
| 868 | [ (*push in occurrences of X...*) | |
| 869 | (REPEAT o CHANGED) | |
| 59780 | 870 |          (Rule_Insts.res_inst_tac ctxt [((("x", 1), Position.none), "X")] []
 | 
| 871 | (insert_commute RS ssubst) 1), | |
| 42793 | 872 | (*...allowing further simplifications*) | 
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
51702diff
changeset | 873 | simp_tac ctxt 1, | 
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
58889diff
changeset | 874 | REPEAT (FIRSTGOAL (resolve_tac ctxt [allI,impI,notI,conjI,iffI])), | 
| 42793 | 875 | DEPTH_SOLVE (atomic_spy_analz_tac ctxt 1)]) i); | 
| 63167 | 876 | \<close> | 
| 14218 | 877 | (*>*) | 
| 878 | ||
| 14199 | 879 | |
| 880 | (*By default only o_apply is built-in. But in the presence of eta-expansion | |
| 881 | this means that some terms displayed as (f o g) will be rewritten, and others | |
| 882 | will not!*) | |
| 883 | declare o_def [simp] | |
| 884 | ||
| 885 | ||
| 886 | lemma Crypt_notin_image_Key [simp]: "Crypt K X \<notin> Key ` A" | |
| 887 | by auto | |
| 888 | ||
| 889 | lemma Hash_notin_image_Key [simp] :"Hash X \<notin> Key ` A" | |
| 890 | by auto | |
| 891 | ||
| 67613 | 892 | lemma synth_analz_mono: "G\<subseteq>H ==> synth (analz(G)) \<subseteq> synth (analz(H))" | 
| 14199 | 893 | by (simp add: synth_mono analz_mono) | 
| 894 | ||
| 895 | lemma Fake_analz_eq [simp]: | |
| 896 | "X \<in> synth(analz H) ==> synth (analz (insert X H)) = synth (analz H)" | |
| 897 | apply (drule Fake_analz_insert[of _ _ "H"]) | |
| 898 | apply (simp add: synth_increasing[THEN Un_absorb2]) | |
| 899 | apply (drule synth_mono) | |
| 900 | apply (simp add: synth_idem) | |
| 901 | apply (blast intro: synth_analz_mono [THEN [2] rev_subsetD]) | |
| 902 | done | |
| 903 | ||
| 63167 | 904 | text\<open>Two generalizations of \<open>analz_insert_eq\<close>\<close> | 
| 14199 | 905 | lemma gen_analz_insert_eq [rule_format]: | 
| 67613 | 906 | "X \<in> analz H ==> \<forall>G. H \<subseteq> G \<longrightarrow> analz (insert X G) = analz G" | 
| 14199 | 907 | by (blast intro: analz_cut analz_insertI analz_mono [THEN [2] rev_subsetD]) | 
| 908 | ||
| 909 | lemma synth_analz_insert_eq [rule_format]: | |
| 910 | "X \<in> synth (analz H) | |
| 67613 | 911 | \<Longrightarrow> \<forall>G. H \<subseteq> G \<longrightarrow> (Key K \<in> analz (insert X G)) = (Key K \<in> analz G)" | 
| 14199 | 912 | apply (erule synth.induct) | 
| 913 | apply (simp_all add: gen_analz_insert_eq subset_trans [OF _ subset_insertI]) | |
| 914 | done | |
| 915 | ||
| 916 | lemma Fake_parts_sing: | |
| 58860 | 917 |      "X \<in> synth (analz H) ==> parts{X} \<subseteq> synth (analz H) \<union> parts H"
 | 
| 14199 | 918 | apply (rule subset_trans) | 
| 919 | apply (erule_tac [2] Fake_parts_insert) | |
| 920 | apply (simp add: parts_mono) | |
| 921 | done | |
| 922 | ||
| 923 | lemmas Fake_parts_sing_imp_Un = Fake_parts_sing [THEN [2] rev_subsetD] | |
| 924 | ||
| 63167 | 925 | method_setup spy_analz = \<open> | 
| 926 | Scan.succeed (SIMPLE_METHOD' o spy_analz_tac)\<close> | |
| 14199 | 927 | "for proving the Fake case when analz is involved" | 
| 928 | ||
| 63167 | 929 | method_setup atomic_spy_analz = \<open> | 
| 930 | Scan.succeed (SIMPLE_METHOD' o atomic_spy_analz_tac)\<close> | |
| 14199 | 931 | "for debugging spy_analz" | 
| 932 | ||
| 63167 | 933 | method_setup Fake_insert_simp = \<open> | 
| 934 | Scan.succeed (SIMPLE_METHOD' o Fake_insert_simp_tac)\<close> | |
| 14199 | 935 | "for debugging spy_analz" | 
| 936 | ||
| 937 | end |