src/HOL/Auth/Shared.thy
changeset 13926 6e62e5357a10
parent 13907 2bc462b99e70
child 13956 8fe7e12290e1
equal deleted inserted replaced
13925:761af5c2fd59 13926:6e62e5357a10
     6 Theory of Shared Keys (common to all symmetric-key protocols)
     6 Theory of Shared Keys (common to all symmetric-key protocols)
     7 
     7 
     8 Shared, long-term keys; initial states of agents
     8 Shared, long-term keys; initial states of agents
     9 *)
     9 *)
    10 
    10 
    11 theory Shared = Event
    11 theory Shared = Event:
    12 files ("Shared_lemmas.ML"):
       
    13 
    12 
    14 consts
    13 consts
    15   shrK    :: "agent => key"  (*symmetric keys*)
    14   shrK    :: "agent => key"  (*symmetric keys*)
    16 
    15 
    17 axioms
    16 axioms
    23   initState_Server:  "initState Server     = Key ` range shrK"
    22   initState_Server:  "initState Server     = Key ` range shrK"
    24   initState_Friend:  "initState (Friend i) = {Key (shrK (Friend i))}"
    23   initState_Friend:  "initState (Friend i) = {Key (shrK (Friend i))}"
    25   initState_Spy:     "initState Spy        = Key`shrK`bad"
    24   initState_Spy:     "initState Spy        = Key`shrK`bad"
    26 
    25 
    27 
    26 
       
    27 subsection{*Basic properties of shrK*}
       
    28 
       
    29 (*Injectiveness: Agents' long-term keys are distinct.*)
       
    30 declare inj_shrK [THEN inj_eq, iff]
       
    31 
       
    32 lemma invKey_K [simp]: "invKey K = K"
       
    33 apply (insert isSym_keys)
       
    34 apply (simp add: symKeys_def) 
       
    35 done
       
    36 
       
    37 
       
    38 lemma analz_Decrypt' [dest]:
       
    39      "[| Crypt K X \<in> analz H;  Key K  \<in> analz H |] ==> X \<in> analz H"
       
    40 by auto
       
    41 
       
    42 text{*Now cancel the @{text dest} attribute given to
       
    43  @{text analz.Decrypt} in its declaration.*}
       
    44 ML
       
    45 {*
       
    46 Delrules [analz.Decrypt];
       
    47 *}
       
    48 
       
    49 text{*Rewrites should not refer to  @{term "initState(Friend i)"} because
       
    50   that expression is not in normal form.*}
       
    51 
       
    52 lemma keysFor_parts_initState [simp]: "keysFor (parts (initState C)) = {}"
       
    53 apply (unfold keysFor_def)
       
    54 apply (induct_tac "C", auto)
       
    55 done
       
    56 
       
    57 (*Specialized to shared-key model: no @{term invKey}*)
       
    58 lemma keysFor_parts_insert:
       
    59      "[| K \<in> keysFor (parts (insert X G));  X \<in> synth (analz H) |] \
       
    60 \     ==> K \<in> keysFor (parts (G \<union> H)) | Key K \<in> parts H";
       
    61 by (force dest: Event.keysFor_parts_insert)  
       
    62 
       
    63 lemma Crypt_imp_keysFor: "Crypt K X \<in> H ==> K \<in> keysFor H"
       
    64 by (drule Crypt_imp_invKey_keysFor, simp)
       
    65 
       
    66 
       
    67 subsection{*Function "knows"*}
       
    68 
       
    69 (*Spy sees shared keys of agents!*)
       
    70 lemma Spy_knows_Spy_bad [intro!]: "A: bad ==> Key (shrK A) \<in> knows Spy evs"
       
    71 apply (induct_tac "evs")
       
    72 apply (simp_all (no_asm_simp) add: imageI knows_Cons split add: event.split)
       
    73 done
       
    74 
       
    75 (*For case analysis on whether or not an agent is compromised*)
       
    76 lemma Crypt_Spy_analz_bad: "[| Crypt (shrK A) X \<in> analz (knows Spy evs);  A: bad |]  
       
    77       ==> X \<in> analz (knows Spy evs)"
       
    78 apply (force dest!: analz.Decrypt)
       
    79 done
       
    80 
       
    81 
       
    82 (** Fresh keys never clash with long-term shared keys **)
       
    83 
       
    84 (*Agents see their own shared keys!*)
       
    85 lemma shrK_in_initState [iff]: "Key (shrK A) \<in> initState A"
       
    86 by (induct_tac "A", auto)
       
    87 
       
    88 lemma shrK_in_used [iff]: "Key (shrK A) \<in> used evs"
       
    89 by (rule initState_into_used, blast)
       
    90 
       
    91 (*Used in parts_induct_tac and analz_Fake_tac to distinguish session keys
       
    92   from long-term shared keys*)
       
    93 lemma Key_not_used [simp]: "Key K \<notin> used evs ==> K \<notin> range shrK"
       
    94 by blast
       
    95 
       
    96 lemma shrK_neq [simp]: "Key K \<notin> used evs ==> shrK B \<noteq> K"
       
    97 by blast
       
    98 
       
    99 declare shrK_neq [THEN not_sym, simp]
       
   100 
       
   101 
       
   102 subsection{*Fresh nonces*}
       
   103 
       
   104 lemma Nonce_notin_initState [iff]: "Nonce N \<notin> parts (initState B)"
       
   105 by (induct_tac "B", auto)
       
   106 
       
   107 lemma Nonce_notin_used_empty [simp]: "Nonce N \<notin> used []"
       
   108 apply (simp (no_asm) add: used_Nil)
       
   109 done
       
   110 
       
   111 
       
   112 subsection{*Supply fresh nonces for possibility theorems.*}
       
   113 
       
   114 (*In any trace, there is an upper bound N on the greatest nonce in use.*)
       
   115 lemma Nonce_supply_lemma: "\<exists>N. ALL n. N<=n --> Nonce n \<notin> used evs"
       
   116 apply (induct_tac "evs")
       
   117 apply (rule_tac x = 0 in exI)
       
   118 apply (simp_all (no_asm_simp) add: used_Cons split add: event.split)
       
   119 apply safe
       
   120 apply (rule msg_Nonce_supply [THEN exE], blast elim!: add_leE)+
       
   121 done
       
   122 
       
   123 lemma Nonce_supply1: "\<exists>N. Nonce N \<notin> used evs"
       
   124 by (rule Nonce_supply_lemma [THEN exE], blast)
       
   125 
       
   126 lemma Nonce_supply2: "\<exists>N N'. Nonce N \<notin> used evs & Nonce N' \<notin> used evs' & N \<noteq> N'"
       
   127 apply (cut_tac evs = evs in Nonce_supply_lemma)
       
   128 apply (cut_tac evs = "evs'" in Nonce_supply_lemma, clarify)
       
   129 apply (rule_tac x = N in exI)
       
   130 apply (rule_tac x = "Suc (N+Na) " in exI)
       
   131 apply (simp (no_asm_simp) add: less_not_refl3 le_add1 le_add2 less_Suc_eq_le)
       
   132 done
       
   133 
       
   134 lemma Nonce_supply3: "\<exists>N N' N''. Nonce N \<notin> used evs & Nonce N' \<notin> used evs' &  
       
   135                     Nonce N'' \<notin> used evs'' & N \<noteq> N' & N' \<noteq> N'' & N \<noteq> N''"
       
   136 apply (cut_tac evs = evs in Nonce_supply_lemma)
       
   137 apply (cut_tac evs = "evs'" in Nonce_supply_lemma)
       
   138 apply (cut_tac evs = "evs''" in Nonce_supply_lemma, clarify)
       
   139 apply (rule_tac x = N in exI)
       
   140 apply (rule_tac x = "Suc (N+Na) " in exI)
       
   141 apply (rule_tac x = "Suc (Suc (N+Na+Nb))" in exI)
       
   142 apply (simp (no_asm_simp) add: less_not_refl3 le_add1 le_add2 less_Suc_eq_le)
       
   143 done
       
   144 
       
   145 lemma Nonce_supply: "Nonce (@ N. Nonce N \<notin> used evs) \<notin> used evs"
       
   146 apply (rule Nonce_supply_lemma [THEN exE])
       
   147 apply (rule someI, blast)
       
   148 done
       
   149 
       
   150 subsection{*Supply fresh keys for possibility theorems.*}
       
   151 
    28 axioms
   152 axioms
    29   (*Unlike the corresponding property of nonces, this cannot be proved.
   153   Key_supply_ax:  "finite KK ==> \<exists>K. K \<notin> KK & Key K \<notin> used evs"
       
   154   --{*Unlike the corresponding property of nonces, this cannot be proved.
    30     We have infinitely many agents and there is nothing to stop their
   155     We have infinitely many agents and there is nothing to stop their
    31     long-term keys from exhausting all the natural numbers.  The axiom
   156     long-term keys from exhausting all the natural numbers.  The axiom
    32     assumes that their keys are dispersed so as to leave room for infinitely
   157     assumes that their keys are dispersed so as to leave room for infinitely
    33     many fresh session keys.  We could, alternatively, restrict agents to
   158     many fresh session keys.  We could, alternatively, restrict agents to
    34     an unspecified finite number.*)
   159     an unspecified finite number.  We could however replace @{term"used evs"} 
    35   Key_supply_ax:  "finite KK ==> EX K. K ~: KK & Key K ~: used evs"
   160     by @{term "used []"}.*}
    36 
   161 
    37 use "Shared_lemmas.ML"
   162 lemma Key_supply1: "\<exists>K. Key K \<notin> used evs"
       
   163 by (rule Finites.emptyI [THEN Key_supply_ax, THEN exE], blast)
       
   164 
       
   165 lemma Key_supply2: "\<exists>K K'. Key K \<notin> used evs & Key K' \<notin> used evs' & K \<noteq> K'"
       
   166 apply (cut_tac evs = evs in Finites.emptyI [THEN Key_supply_ax])
       
   167 apply (erule exE)
       
   168 apply (cut_tac evs="evs'" in Finites.emptyI [THEN Finites.insertI, THEN Key_supply_ax], auto) 
       
   169 done
       
   170 
       
   171 lemma Key_supply3: "\<exists>K K' K''. Key K \<notin> used evs & Key K' \<notin> used evs' &  
       
   172                        Key K'' \<notin> used evs'' & K \<noteq> K' & K' \<noteq> K'' & K \<noteq> K''"
       
   173 apply (cut_tac evs = evs in Finites.emptyI [THEN Key_supply_ax])
       
   174 apply (erule exE)
       
   175 (*Blast_tac requires instantiation of the keys for some reason*)
       
   176 apply (cut_tac evs="evs'" and a1 = K in Finites.emptyI [THEN Finites.insertI, THEN Key_supply_ax])
       
   177 apply (erule exE)
       
   178 apply (cut_tac evs = "evs''" and a1 = Ka and a2 = K 
       
   179        in Finites.emptyI [THEN Finites.insertI, THEN Finites.insertI, THEN Key_supply_ax], blast)
       
   180 done
       
   181 
       
   182 lemma Key_supply: "Key (@ K. Key K \<notin> used evs) \<notin> used evs"
       
   183 apply (rule Finites.emptyI [THEN Key_supply_ax, THEN exE])
       
   184 apply (rule someI, blast)
       
   185 done
       
   186 
       
   187 subsection{*Tactics for possibility theorems*}
       
   188 
       
   189 ML
       
   190 {*
       
   191 val inj_shrK      = thm "inj_shrK";
       
   192 val isSym_keys    = thm "isSym_keys";
       
   193 val Key_supply_ax = thm "Key_supply_ax";
       
   194 val Key_supply = thm "Key_supply";
       
   195 val Nonce_supply = thm "Nonce_supply";
       
   196 val invKey_K = thm "invKey_K";
       
   197 val analz_Decrypt' = thm "analz_Decrypt'";
       
   198 val keysFor_parts_initState = thm "keysFor_parts_initState";
       
   199 val keysFor_parts_insert = thm "keysFor_parts_insert";
       
   200 val Crypt_imp_keysFor = thm "Crypt_imp_keysFor";
       
   201 val Spy_knows_Spy_bad = thm "Spy_knows_Spy_bad";
       
   202 val Crypt_Spy_analz_bad = thm "Crypt_Spy_analz_bad";
       
   203 val shrK_in_initState = thm "shrK_in_initState";
       
   204 val shrK_in_used = thm "shrK_in_used";
       
   205 val Key_not_used = thm "Key_not_used";
       
   206 val shrK_neq = thm "shrK_neq";
       
   207 val Nonce_notin_initState = thm "Nonce_notin_initState";
       
   208 val Nonce_notin_used_empty = thm "Nonce_notin_used_empty";
       
   209 val Nonce_supply_lemma = thm "Nonce_supply_lemma";
       
   210 val Nonce_supply1 = thm "Nonce_supply1";
       
   211 val Nonce_supply2 = thm "Nonce_supply2";
       
   212 val Nonce_supply3 = thm "Nonce_supply3";
       
   213 val Nonce_supply = thm "Nonce_supply";
       
   214 val Key_supply1 = thm "Key_supply1";
       
   215 val Key_supply2 = thm "Key_supply2";
       
   216 val Key_supply3 = thm "Key_supply3";
       
   217 val Key_supply = thm "Key_supply";
       
   218 *}
       
   219 
       
   220 
       
   221 ML
       
   222 {*
       
   223 (*Omitting used_Says makes the tactic much faster: it leaves expressions
       
   224     such as  Nonce ?N \<notin> used evs that match Nonce_supply*)
       
   225 fun gen_possibility_tac ss state = state |>
       
   226    (REPEAT 
       
   227     (ALLGOALS (simp_tac (ss delsimps [used_Says, used_Notes, used_Gets] 
       
   228                          setSolver safe_solver))
       
   229      THEN
       
   230      REPEAT_FIRST (eq_assume_tac ORELSE' 
       
   231                    resolve_tac [refl, conjI, Nonce_supply, Key_supply])))
       
   232 
       
   233 (*Tactic for possibility theorems (ML script version)*)
       
   234 fun possibility_tac state = gen_possibility_tac (simpset()) state
       
   235 
       
   236 (*For harder protocols (such as Recur) where we have to set up some
       
   237   nonces and keys initially*)
       
   238 fun basic_possibility_tac st = st |>
       
   239     REPEAT 
       
   240     (ALLGOALS (asm_simp_tac (simpset() setSolver safe_solver))
       
   241      THEN
       
   242      REPEAT_FIRST (resolve_tac [refl, conjI]))
       
   243 *}
       
   244 
       
   245 subsection{*Specialized rewriting for analz_insert_freshK*}
       
   246 
       
   247 lemma subset_Compl_range: "A <= - (range shrK) ==> shrK x \<notin> A"
       
   248 by blast
       
   249 
       
   250 lemma insert_Key_singleton: "insert (Key K) H = Key ` {K} \<union> H"
       
   251 by blast
       
   252 
       
   253 lemma insert_Key_image: "insert (Key K) (Key`KK \<union> C) = Key ` (insert K KK) \<union> C"
       
   254 by blast
       
   255 
       
   256 (** Reverse the normal simplification of "image" to build up (not break down)
       
   257     the set of keys.  Use analz_insert_eq with (Un_upper2 RS analz_mono) to
       
   258     erase occurrences of forwarded message components (X). **)
       
   259 
       
   260 lemmas analz_image_freshK_simps =
       
   261        simp_thms mem_simps --{*these two allow its use with @{text "only:"}*}
       
   262        disj_comms 
       
   263        image_insert [THEN sym] image_Un [THEN sym] empty_subsetI insert_subset
       
   264        analz_insert_eq Un_upper2 [THEN analz_mono, THEN [2] rev_subsetD]
       
   265        insert_Key_singleton subset_Compl_range
       
   266        Key_not_used insert_Key_image Un_assoc [THEN sym]
       
   267 
       
   268 (*Lemma for the trivial direction of the if-and-only-if*)
       
   269 lemma analz_image_freshK_lemma:
       
   270      "(Key K \<in> analz (Key`nE \<union> H)) --> (K \<in> nE | Key K \<in> analz H)  ==>  
       
   271          (Key K \<in> analz (Key`nE \<union> H)) = (K \<in> nE | Key K \<in> analz H)"
       
   272 by (blast intro: analz_mono [THEN [2] rev_subsetD])
       
   273 
       
   274 ML
       
   275 {*
       
   276 val analz_image_freshK_lemma = thm "analz_image_freshK_lemma";
       
   277 
       
   278 val analz_image_freshK_ss = 
       
   279      simpset() delsimps [image_insert, image_Un]
       
   280 	       delsimps [imp_disjL]    (*reduces blow-up*)
       
   281 	       addsimps thms "analz_image_freshK_simps"
       
   282 *}
       
   283 
       
   284 
    38 
   285 
    39 (*Lets blast_tac perform this step without needing the simplifier*)
   286 (*Lets blast_tac perform this step without needing the simplifier*)
    40 lemma invKey_shrK_iff [iff]:
   287 lemma invKey_shrK_iff [iff]:
    41      "(Key (invKey K) \<in> X) = (Key K \<in> X)"
   288      "(Key (invKey K) \<in> X) = (Key K \<in> X)"
    42 by auto
   289 by auto