8 |
8 |
9 open Recur; |
9 open Recur; |
10 |
10 |
11 proof_timing:=true; |
11 proof_timing:=true; |
12 HOL_quantifiers := false; |
12 HOL_quantifiers := false; |
13 Pretty.setdepth 25; |
13 Pretty.setdepth 30; |
14 |
14 |
15 |
15 |
16 (** Possibility properties: traces that reach the end |
16 (** Possibility properties: traces that reach the end |
17 ONE theorem would be more elegant and faster! |
17 ONE theorem would be more elegant and faster! |
18 By induction on a list of agents (no repetitions) |
18 By induction on a list of agents (no repetitions) |
19 **) |
19 **) |
|
20 |
20 |
21 |
21 (*Simplest case: Alice goes directly to the server*) |
22 (*Simplest case: Alice goes directly to the server*) |
22 goal thy |
23 goal thy |
23 "!!A. A ~= Server \ |
24 "!!A. A ~= Server \ |
24 \ ==> EX K NA. EX evs: recur lost. \ |
25 \ ==> EX K NA. EX evs: recur lost. \ |
25 \ Says Server A {|Agent A, \ |
26 \ Says Server A {|Crypt (shrK A) {|Key K, Agent Server, Nonce NA|}, \ |
26 \ Crypt (shrK A) {|Key K, Agent Server, Nonce NA|}, \ |
|
27 \ Agent Server|} \ |
27 \ Agent Server|} \ |
28 \ : set_of_list evs"; |
28 \ : set_of_list evs"; |
29 by (REPEAT (resolve_tac [exI,bexI] 1)); |
29 by (REPEAT (resolve_tac [exI,bexI] 1)); |
30 by (rtac (recur.Nil RS recur.RA1 RS |
30 by (rtac (recur.Nil RS recur.RA1 RS |
31 (respond.One RSN (4,recur.RA3))) 2); |
31 (respond.One RSN (4,recur.RA3))) 2); |
32 by (REPEAT |
32 by possibility_tac; |
33 (ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)) |
|
34 THEN |
|
35 REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]))); |
|
36 result(); |
33 result(); |
37 |
34 |
38 |
35 |
39 (*Case two: Alice, Bob and the server*) |
36 (*Case two: Alice, Bob and the server*) |
40 goal thy |
37 goal thy |
41 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
38 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
42 \ ==> EX K. EX NA. EX evs: recur lost. \ |
39 \ ==> EX K. EX NA. EX evs: recur lost. \ |
43 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
40 \ Says B A {|Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
44 \ Agent Server|} \ |
41 \ Agent Server|} \ |
45 \ : set_of_list evs"; |
42 \ : set_of_list evs"; |
|
43 by (cut_facts_tac [Nonce_supply2, Key_supply2] 1); |
|
44 by (REPEAT (eresolve_tac [exE, conjE] 1)); |
46 by (REPEAT (resolve_tac [exI,bexI] 1)); |
45 by (REPEAT (resolve_tac [exI,bexI] 1)); |
47 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS |
46 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS |
48 (respond.One RS respond.Cons RSN (4,recur.RA3)) RS |
47 (respond.One RS respond.Cons RSN (4,recur.RA3)) RS |
49 recur.RA4) 2); |
48 recur.RA4) 2); |
50 bw HPair_def; |
49 by basic_possibility_tac; |
51 by (REPEAT |
50 by (DEPTH_SOLVE (eresolve_tac [asm_rl, less_not_refl2, |
52 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
51 less_not_refl2 RS not_sym] 1)); |
53 THEN |
|
54 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
|
55 result(); |
52 result(); |
56 |
53 |
57 |
54 |
58 (*Case three: Alice, Bob, Charlie and the server*) |
55 (*Case three: Alice, Bob, Charlie and the server |
59 goal thy |
56 goal thy |
60 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
57 "!!A B. [| A ~= B; B ~= C; A ~= Server; B ~= Server; C ~= Server |] \ |
61 \ ==> EX K. EX NA. EX evs: recur lost. \ |
58 \ ==> EX K. EX NA. EX evs: recur lost. \ |
62 \ Says B A {|Agent A, Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
59 \ Says B A {|Crypt (shrK A) {|Key K, Agent B, Nonce NA|}, \ |
63 \ Agent Server|} \ |
60 \ Agent Server|} \ |
64 \ : set_of_list evs"; |
61 \ : set_of_list evs"; |
|
62 by (cut_facts_tac [Nonce_supply3, Key_supply3] 1); |
|
63 by (REPEAT (eresolve_tac [exE, conjE] 1)); |
65 by (REPEAT (resolve_tac [exI,bexI] 1)); |
64 by (REPEAT (resolve_tac [exI,bexI] 1)); |
66 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS |
65 by (rtac (recur.Nil RS recur.RA1 RS recur.RA2 RS recur.RA2 RS |
67 (respond.One RS respond.Cons RS respond.Cons RSN |
66 (respond.One RS respond.Cons RS respond.Cons RSN |
68 (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2); |
67 (4,recur.RA3)) RS recur.RA4 RS recur.RA4) 2); |
69 bw HPair_def; |
68 (*SLOW: 70 seconds*) |
70 by (REPEAT (*SLOW: 37 seconds*) |
69 by basic_possibility_tac; |
71 (REPEAT_FIRST (eq_assume_tac ORELSE' resolve_tac [refl, conjI]) |
70 by (DEPTH_SOLVE (swap_res_tac [refl, conjI, disjCI] 1 |
72 THEN |
71 ORELSE |
73 ALLGOALS (asm_simp_tac (!simpset setsolver safe_solver)))); |
72 eresolve_tac [asm_rl, less_not_refl2, |
74 by (ALLGOALS |
73 less_not_refl2 RS not_sym] 1)); |
75 (SELECT_GOAL (DEPTH_SOLVE |
|
76 (swap_res_tac [refl, conjI, disjI1, disjI2] 1 APPEND |
|
77 etac not_sym 1)))); |
|
78 result(); |
74 result(); |
79 |
75 ****************) |
80 |
|
81 |
76 |
82 (**** Inductive proofs about recur ****) |
77 (**** Inductive proofs about recur ****) |
83 |
78 |
84 (*Monotonicity*) |
79 (*Monotonicity*) |
85 goal thy "!!evs. lost' <= lost ==> recur lost' <= recur lost"; |
80 goal thy "!!evs. lost' <= lost ==> recur lost' <= recur lost"; |
97 qed_spec_mp "not_Says_to_self"; |
92 qed_spec_mp "not_Says_to_self"; |
98 Addsimps [not_Says_to_self]; |
93 Addsimps [not_Says_to_self]; |
99 AddSEs [not_Says_to_self RSN (2, rev_notE)]; |
94 AddSEs [not_Says_to_self RSN (2, rev_notE)]; |
100 |
95 |
101 |
96 |
|
97 |
|
98 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> Key KAB : parts{RB}"; |
|
99 by (etac respond.induct 1); |
|
100 by (ALLGOALS Simp_tac); |
|
101 qed "respond_Key_in_parts"; |
|
102 |
|
103 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> Key KAB ~: used evs"; |
|
104 by (etac respond.induct 1); |
|
105 by (REPEAT (assume_tac 1)); |
|
106 qed "respond_imp_not_used"; |
|
107 |
|
108 goal thy |
|
109 "!!evs. [| Key K : parts {RB}; (PB,RB,K') : respond evs |] \ |
|
110 \ ==> Key K ~: used evs"; |
|
111 by (etac rev_mp 1); |
|
112 by (etac respond.induct 1); |
|
113 by (auto_tac(!claset addDs [Key_not_used, respond_imp_not_used], |
|
114 !simpset)); |
|
115 qed_spec_mp "Key_in_parts_respond"; |
|
116 |
102 (*Simple inductive reasoning about responses*) |
117 (*Simple inductive reasoning about responses*) |
103 goal thy "!!j. (j,PA,RB) : respond i ==> RB : responses i"; |
118 goal thy "!!evs. (PA,RB,KAB) : respond evs ==> RB : responses evs"; |
104 by (etac respond.induct 1); |
119 by (etac respond.induct 1); |
105 by (REPEAT (ares_tac responses.intrs 1)); |
120 by (REPEAT (ares_tac (respond_imp_not_used::responses.intrs) 1)); |
106 qed "respond_imp_responses"; |
121 qed "respond_imp_responses"; |
107 |
122 |
108 |
123 |
109 (** For reasoning about the encrypted portion of messages **) |
124 (** For reasoning about the encrypted portion of messages **) |
110 |
125 |
111 val RA2_analz_sees_Spy = Says_imp_sees_Spy RS analz.Inj |> standard; |
126 val RA2_analz_sees_Spy = Says_imp_sees_Spy RS analz.Inj |> standard; |
112 |
127 |
113 goal thy "!!evs. Says C' B {|Agent B, X, Agent B, X', RA|} : set_of_list evs \ |
128 goal thy "!!evs. Says C' B {|X, X', RA|} : set_of_list evs \ |
114 \ ==> RA : analz (sees lost Spy evs)"; |
129 \ ==> RA : analz (sees lost Spy evs)"; |
115 by (fast_tac (!claset addSDs [Says_imp_sees_Spy RS analz.Inj]) 1); |
130 by (fast_tac (!claset addSDs [Says_imp_sees_Spy RS analz.Inj]) 1); |
116 qed "RA4_analz_sees_Spy"; |
131 qed "RA4_analz_sees_Spy"; |
117 |
132 |
118 (*RA2_analz... and RA4_analz... let us treat those cases using the same |
133 (*RA2_analz... and RA4_analz... let us treat those cases using the same |
187 |
194 |
188 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D); |
195 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D); |
189 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D]; |
196 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D]; |
190 |
197 |
191 |
198 |
192 (*** Future keys can't be seen or used! ***) |
199 |
193 |
200 (** Nobody can have used non-existent keys! **) |
194 (*Nobody can have SEEN keys that will be generated in the future. *) |
201 |
195 goal thy "!!evs. evs : recur lost ==> \ |
202 goal thy |
196 \ length evs <= i --> \ |
203 "!!evs. [| K : keysFor (parts {RB}); (PB,RB,K') : respond evs |] \ |
197 \ Key (newK2(i,j)) ~: parts (sees lost Spy evs)"; |
204 \ ==> K : range shrK"; |
198 by (parts_induct_tac 1); |
205 by (etac rev_mp 1); |
199 (*RA2*) |
206 by (etac (respond_imp_responses RS responses.induct) 1); |
200 by (best_tac (!claset addSEs partsEs |
|
201 addSDs [parts_cut] |
|
202 addDs [Suc_leD] |
|
203 addss (!simpset)) 3); |
|
204 (*Fake*) |
|
205 by (best_tac (!claset addDs [impOfSubs analz_subset_parts, |
|
206 impOfSubs parts_insert_subset_Un, |
|
207 Suc_leD] |
|
208 addss (!simpset)) 1); |
|
209 (*For RA3*) |
|
210 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 2); |
|
211 (*RA1-RA4*) |
|
212 by (REPEAT (best_tac (!claset addDs [Key_in_parts_respond, Suc_leD] |
|
213 addss (!simpset)) 1)); |
|
214 qed_spec_mp "new_keys_not_seen"; |
|
215 Addsimps [new_keys_not_seen]; |
|
216 |
|
217 (*Variant: old messages must contain old keys!*) |
|
218 goal thy |
|
219 "!!evs. [| Says A B X : set_of_list evs; \ |
|
220 \ Key (newK2(i,j)) : parts {X}; \ |
|
221 \ evs : recur lost \ |
|
222 \ |] ==> i < length evs"; |
|
223 by (rtac ccontr 1); |
|
224 by (dtac leI 1); |
|
225 by (fast_tac (!claset addSDs [new_keys_not_seen, Says_imp_sees_Spy] |
|
226 addIs [impOfSubs parts_mono]) 1); |
|
227 qed "Says_imp_old_keys"; |
|
228 |
|
229 |
|
230 (*** Future nonces can't be seen or used! ***) |
|
231 |
|
232 goal thy |
|
233 "!!evs. (j, PB, RB) : respond i \ |
|
234 \ ==> Nonce N : parts {RB} --> Nonce N : parts {PB}"; |
|
235 be respond.induct 1; |
|
236 by (Auto_tac()); |
207 by (Auto_tac()); |
237 qed_spec_mp "Nonce_in_parts_respond"; |
208 qed_spec_mp "Key_in_keysFor_parts"; |
238 |
209 |
239 |
210 |
240 goal thy "!!i. evs : recur lost ==> \ |
211 goal thy "!!evs. evs : recur lost ==> \ |
241 \ length evs <= i --> Nonce(newN i) ~: parts (sees lost Spy evs)"; |
212 \ Key K ~: used evs --> K ~: keysFor (parts (sees lost Spy evs))"; |
242 by (parts_induct_tac 1); |
|
243 (*For RA3*) |
|
244 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 4); |
|
245 by (deepen_tac (!claset addSDs [Says_imp_sees_Spy RS parts.Inj] |
|
246 addDs [Nonce_in_parts_respond, parts_cut, Suc_leD] |
|
247 addss (!simpset)) 0 4); |
|
248 (*Fake*) |
|
249 by (fast_tac (!claset addDs [impOfSubs analz_subset_parts, |
|
250 impOfSubs parts_insert_subset_Un, |
|
251 Suc_leD] |
|
252 addss (!simpset)) 1); |
|
253 (*RA1, RA2, RA4*) |
|
254 by (REPEAT_FIRST (fast_tac (!claset |
|
255 addSEs partsEs |
|
256 addEs [leD RS notE] |
|
257 addDs [Suc_leD] |
|
258 addss (!simpset)))); |
|
259 qed_spec_mp "new_nonces_not_seen"; |
|
260 Addsimps [new_nonces_not_seen]; |
|
261 |
|
262 (*Variant: old messages must contain old nonces!*) |
|
263 goal thy "!!evs. [| Says A B X : set_of_list evs; \ |
|
264 \ Nonce (newN i) : parts {X}; \ |
|
265 \ evs : recur lost \ |
|
266 \ |] ==> i < length evs"; |
|
267 by (rtac ccontr 1); |
|
268 by (dtac leI 1); |
|
269 by (fast_tac (!claset addSDs [new_nonces_not_seen, Says_imp_sees_Spy] |
|
270 addIs [impOfSubs parts_mono]) 1); |
|
271 qed "Says_imp_old_nonces"; |
|
272 |
|
273 |
|
274 (** Nobody can have USED keys that will be generated in the future. **) |
|
275 |
|
276 goal thy |
|
277 "!!evs. (j,PB,RB) : respond i \ |
|
278 \ ==> K : keysFor (parts {RB}) --> (EX A. K = shrK A)"; |
|
279 be (respond_imp_responses RS responses.induct) 1; |
|
280 by (Auto_tac()); |
|
281 qed_spec_mp "Key_in_keysFor_parts_respond"; |
|
282 |
|
283 |
|
284 goal thy "!!i. evs : recur lost ==> \ |
|
285 \ length evs <= i --> newK2(i,j) ~: keysFor (parts (sees lost Spy evs))"; |
|
286 by (parts_induct_tac 1); |
213 by (parts_induct_tac 1); |
287 (*RA3*) |
214 (*RA3*) |
288 by (fast_tac (!claset addDs [Key_in_keysFor_parts_respond, Suc_leD] |
215 by (best_tac (!claset addDs [Key_in_keysFor_parts] |
289 addss (!simpset addsimps [parts_insert_sees])) 4); |
216 addss (!simpset addsimps [parts_insert_sees])) 2); |
290 (*RA2*) |
217 (*Fake*) |
291 by (fast_tac (!claset addSEs partsEs |
218 by (best_tac |
292 addDs [Suc_leD] addss (!simpset)) 3); |
219 (!claset addIs [impOfSubs analz_subset_parts] |
293 (*Fake, RA1, RA4*) |
220 addDs [impOfSubs (analz_subset_parts RS keysFor_mono), |
294 by (REPEAT |
221 impOfSubs (parts_insert_subset_Un RS keysFor_mono)] |
295 (best_tac |
222 addss (!simpset)) 1); |
296 (!claset addDs [impOfSubs (analz_subset_parts RS keysFor_mono), |
|
297 impOfSubs (parts_insert_subset_Un RS keysFor_mono), |
|
298 Suc_leD] |
|
299 addEs [new_keys_not_seen RS not_parts_not_analz RSN(2,rev_notE)] |
|
300 addss (!simpset)) 1)); |
|
301 qed_spec_mp "new_keys_not_used"; |
223 qed_spec_mp "new_keys_not_used"; |
302 |
224 |
303 |
225 |
304 bind_thm ("new_keys_not_analzd", |
226 bind_thm ("new_keys_not_analzd", |
305 [analz_subset_parts RS keysFor_mono, |
227 [analz_subset_parts RS keysFor_mono, |
317 dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN |
239 dres_inst_tac [("lost","lost")] RA2_analz_sees_Spy 4 THEN |
318 forward_tac [respond_imp_responses] 5 THEN |
240 forward_tac [respond_imp_responses] 5 THEN |
319 dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6; |
241 dres_inst_tac [("lost","lost")] RA4_analz_sees_Spy 6; |
320 |
242 |
321 |
243 |
322 Delsimps [image_insert]; |
|
323 |
|
324 (** Session keys are not used to encrypt other session keys **) |
244 (** Session keys are not used to encrypt other session keys **) |
325 |
245 |
326 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
246 (*Version for "responses" relation. Handles case RA3 in the theorem below. |
327 Note that it holds for *any* set H (not just "sees lost Spy evs") |
247 Note that it holds for *any* set H (not just "sees lost Spy evs") |
328 satisfying the inductive hypothesis.*) |
248 satisfying the inductive hypothesis.*) |
329 goal thy |
249 goal thy |
330 "!!evs. [| RB : responses i; \ |
250 "!!evs. [| RB : responses evs; \ |
331 \ ALL K I. (Key K : analz (Key``(newK``I) Un H)) = \ |
251 \ ALL K KK. KK <= Compl (range shrK) --> \ |
332 \ (K : newK``I | Key K : analz H) |] \ |
252 \ (Key K : analz (Key``KK Un H)) = \ |
333 \ ==> ALL K I. (Key K : analz (insert RB (Key``(newK``I) Un H))) = \ |
253 \ (K : KK | Key K : analz H) |] \ |
334 \ (K : newK``I | Key K : analz (insert RB H))"; |
254 \ ==> ALL K KK. KK <= Compl (range shrK) --> \ |
335 be responses.induct 1; |
255 \ (Key K : analz (insert RB (Key``KK Un H))) = \ |
336 by (ALLGOALS |
256 \ (K : KK | Key K : analz (insert RB H))"; |
337 (asm_simp_tac |
257 by (etac responses.induct 1); |
338 (!simpset addsimps [insert_Key_singleton, insert_Key_image, |
258 by (ALLGOALS (asm_simp_tac analz_image_freshK_ss)); |
339 Un_assoc RS sym, pushKey_newK] |
259 qed "resp_analz_image_freshK_lemma"; |
340 setloop split_tac [expand_if]))); |
|
341 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1); |
|
342 qed "resp_analz_image_newK_lemma"; |
|
343 |
260 |
344 (*Version for the protocol. Proof is almost trivial, thanks to the lemma.*) |
261 (*Version for the protocol. Proof is almost trivial, thanks to the lemma.*) |
345 goal thy |
262 goal thy |
346 "!!evs. evs : recur lost ==> \ |
263 "!!evs. evs : recur lost ==> \ |
347 \ ALL K I. (Key K : analz (Key``(newK``I) Un (sees lost Spy evs))) = \ |
264 \ ALL K KK. KK <= Compl (range shrK) --> \ |
348 \ (K : newK``I | Key K : analz (sees lost Spy evs))"; |
265 \ (Key K : analz (Key``KK Un (sees lost Spy evs))) = \ |
|
266 \ (K : KK | Key K : analz (sees lost Spy evs))"; |
349 by (etac recur.induct 1); |
267 by (etac recur.induct 1); |
350 by analz_Fake_tac; |
268 by analz_Fake_tac; |
351 by (REPEAT_FIRST (ares_tac [allI, analz_image_newK_lemma])); |
269 by (REPEAT_FIRST (resolve_tac [allI, impI])); |
352 by (ALLGOALS (asm_simp_tac (!simpset addsimps [resp_analz_image_newK_lemma]))); |
270 by (REPEAT_FIRST (rtac analz_image_freshK_lemma )); |
|
271 by (ALLGOALS |
|
272 (asm_simp_tac |
|
273 (analz_image_freshK_ss addsimps [resp_analz_image_freshK_lemma]))); |
353 (*Base*) |
274 (*Base*) |
354 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1); |
275 by (fast_tac (!claset addIs [image_eqI] addss (!simpset)) 1); |
355 (*RA4, RA2, Fake*) |
276 (*RA4, RA2, Fake*) |
356 by (REPEAT (spy_analz_tac 1)); |
277 by (REPEAT (spy_analz_tac 1)); |
357 val raw_analz_image_newK = result(); |
278 val raw_analz_image_freshK = result(); |
358 qed_spec_mp "analz_image_newK"; |
279 qed_spec_mp "analz_image_freshK"; |
359 |
280 |
360 |
281 |
361 (*Instance of the lemma with H replaced by (sees lost Spy evs): |
282 (*Instance of the lemma with H replaced by (sees lost Spy evs): |
362 [| RB : responses i; evs : recur lost |] |
283 [| RB : responses evs; evs : recur lost; |] |
363 ==> Key xa : analz (insert RB (Key``newK``x Un sees lost Spy evs)) = |
284 ==> KK <= Compl (range shrK) --> |
364 (xa : newK``x | Key xa : analz (insert RB (sees lost Spy evs))) |
285 Key K : analz (insert RB (Key``KK Un sees lost Spy evs)) = |
|
286 (K : KK | Key K : analz (insert RB (sees lost Spy evs))) |
365 *) |
287 *) |
366 bind_thm ("resp_analz_image_newK", |
288 bind_thm ("resp_analz_image_freshK", |
367 raw_analz_image_newK RSN |
289 raw_analz_image_freshK RSN |
368 (2, resp_analz_image_newK_lemma) RS spec RS spec); |
290 (2, resp_analz_image_freshK_lemma) RS spec RS spec); |
369 |
291 |
370 goal thy |
292 goal thy |
371 "!!evs. evs : recur lost ==> \ |
293 "!!evs. [| evs : recur lost; KAB ~: range shrK |] ==> \ |
372 \ Key K : analz (insert (Key (newK x)) (sees lost Spy evs)) = \ |
294 \ Key K : analz (insert (Key KAB) (sees lost Spy evs)) = \ |
373 \ (K = newK x | Key K : analz (sees lost Spy evs))"; |
295 \ (K = KAB | Key K : analz (sees lost Spy evs))"; |
374 by (asm_simp_tac (HOL_ss addsimps [pushKey_newK, analz_image_newK, |
296 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1); |
375 insert_Key_singleton]) 1); |
297 qed "analz_insert_freshK"; |
376 by (Fast_tac 1); |
298 |
377 qed "analz_insert_Key_newK"; |
299 |
378 |
300 (*Everything that's hashed is already in past traffic. *) |
379 |
|
380 (*This is more general than proving Hash_new_nonces_not_seen: we don't prove |
|
381 that "future nonces" can't be hashed, but that everything that's hashed is |
|
382 already in past traffic. *) |
|
383 goal thy "!!i. [| evs : recur lost; A ~: lost |] ==> \ |
301 goal thy "!!i. [| evs : recur lost; A ~: lost |] ==> \ |
384 \ Hash {|Key(shrK A), X|} : parts (sees lost Spy evs) --> \ |
302 \ Hash {|Key(shrK A), X|} : parts (sees lost Spy evs) --> \ |
385 \ X : parts (sees lost Spy evs)"; |
303 \ X : parts (sees lost Spy evs)"; |
386 be recur.induct 1; |
304 by (etac recur.induct 1); |
387 by parts_Fake_tac; |
305 by parts_Fake_tac; |
388 (*RA3 requires a further induction*) |
306 (*RA3 requires a further induction*) |
389 be responses.induct 5; |
307 by (etac responses.induct 5); |
390 by (ALLGOALS Asm_simp_tac); |
308 by (ALLGOALS Asm_simp_tac); |
391 (*Fake*) |
309 (*Fake*) |
392 by (best_tac (!claset addDs [impOfSubs analz_subset_parts, |
310 by (best_tac (!claset addDs [impOfSubs analz_subset_parts, |
393 impOfSubs Fake_parts_insert] |
311 impOfSubs Fake_parts_insert] |
394 addss (!simpset addsimps [parts_insert_sees])) 2); |
312 addss (!simpset addsimps [parts_insert_sees])) 2); |
395 (*Two others*) |
313 (*Two others*) |
396 by (REPEAT (fast_tac (!claset addss (!simpset)) 1)); |
314 by (REPEAT (fast_tac (!claset addss (!simpset)) 1)); |
397 bind_thm ("Hash_imp_body", result() RSN (2, rev_mp)); |
315 bind_thm ("Hash_imp_body", result() RSN (2, rev_mp)); |
398 |
316 |
399 |
317 |
400 (** The Nonce NA uniquely identifies A's message. |
318 (** The Nonce NA uniquely identifies A's message. |
401 This theorem applies to rounds RA1 and RA2! |
319 This theorem applies to steps RA1 and RA2! |
402 |
320 |
403 Unicity is not used in other proofs but is desirable in its own right. |
321 Unicity is not used in other proofs but is desirable in its own right. |
404 **) |
322 **) |
405 |
323 |
406 goal thy |
324 goal thy |
407 "!!evs. [| evs : recur lost; A ~: lost |] \ |
325 "!!evs. [| evs : recur lost; A ~: lost |] \ |
408 \ ==> EX B' P'. ALL B P. \ |
326 \ ==> EX B' P'. ALL B P. \ |
409 \ Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \ |
327 \ Hash {|Key(shrK A), Agent A, Agent B, Nonce NA, P|} \ |
410 \ : parts (sees lost Spy evs) --> B=B' & P=P'"; |
328 \ : parts (sees lost Spy evs) --> B=B' & P=P'"; |
411 by (parts_induct_tac 1); |
329 by (parts_induct_tac 1); |
412 be responses.induct 3; |
330 by (etac responses.induct 3); |
413 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); |
331 by (ALLGOALS (simp_tac (!simpset addsimps [all_conj_distrib]))); |
414 by (step_tac (!claset addSEs partsEs) 1); |
332 by (step_tac (!claset addSEs partsEs) 1); |
415 (*RA1: creation of new Nonce. Move assertion into global context*) |
333 (*RA1,2: creation of new Nonce. Move assertion into global context*) |
416 by (expand_case_tac "NA = ?y" 1); |
334 by (ALLGOALS (expand_case_tac "NA = ?y")); |
417 by (best_tac (!claset addSIs [exI] |
335 by (REPEAT_FIRST (ares_tac [exI])); |
418 addSDs [Hash_imp_body] |
336 by (REPEAT (best_tac (!claset addSDs [Hash_imp_body] |
419 addSEs (new_nonces_not_seen::partsEs) |
337 addSEs sees_Spy_partsEs) 1)); |
420 addss (!simpset)) 1); |
|
421 by (best_tac (!claset addss (!simpset)) 1); |
|
422 (*RA2: creation of new Nonce*) |
|
423 by (expand_case_tac "NA = ?y" 1); |
|
424 by (best_tac (!claset addSIs [exI] |
|
425 addSDs [Hash_imp_body] |
|
426 addSEs (new_nonces_not_seen::partsEs) |
|
427 addss (!simpset)) 1); |
|
428 by (best_tac (!claset addss (!simpset)) 1); |
|
429 val lemma = result(); |
338 val lemma = result(); |
430 |
339 |
431 goalw thy [HPair_def] |
340 goalw thy [HPair_def] |
432 "!!evs.[| HPair (Key(shrK A)) {|Agent A, Agent B, Nonce NA, P|} \ |
341 "!!evs.[| Hash[Key(shrK A)] {|Agent A, Agent B, Nonce NA, P|} \ |
433 \ : parts (sees lost Spy evs); \ |
342 \ : parts (sees lost Spy evs); \ |
434 \ HPair (Key(shrK A)) {|Agent A, Agent B', Nonce NA, P'|} \ |
343 \ Hash[Key(shrK A)] {|Agent A, Agent B', Nonce NA, P'|} \ |
435 \ : parts (sees lost Spy evs); \ |
344 \ : parts (sees lost Spy evs); \ |
436 \ evs : recur lost; A ~: lost |] \ |
345 \ evs : recur lost; A ~: lost |] \ |
437 \ ==> B=B' & P=P'"; |
346 \ ==> B=B' & P=P'"; |
438 by (REPEAT (eresolve_tac partsEs 1)); |
347 by (REPEAT (eresolve_tac partsEs 1)); |
439 by (prove_unique_tac lemma 1); |
348 by (prove_unique_tac lemma 1); |
443 (*** Lemmas concerning the Server's response |
352 (*** Lemmas concerning the Server's response |
444 (relations "respond" and "responses") |
353 (relations "respond" and "responses") |
445 ***) |
354 ***) |
446 |
355 |
447 goal thy |
356 goal thy |
448 "!!evs. [| RB : responses i; evs : recur lost |] \ |
357 "!!evs. [| RB : responses evs; evs : recur lost |] \ |
449 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)"; |
358 \ ==> (Key (shrK B) : analz (insert RB (sees lost Spy evs))) = (B:lost)"; |
450 be responses.induct 1; |
359 by (etac responses.induct 1); |
451 by (ALLGOALS |
360 by (ALLGOALS |
452 (asm_simp_tac |
361 (asm_simp_tac |
453 (!simpset addsimps [resp_analz_image_newK, insert_Key_singleton] |
362 (analz_image_freshK_ss addsimps [Spy_analz_shrK, |
454 setloop split_tac [expand_if]))); |
363 resp_analz_image_freshK]))); |
455 qed "shrK_in_analz_respond"; |
364 qed "shrK_in_analz_respond"; |
456 Addsimps [shrK_in_analz_respond]; |
365 Addsimps [shrK_in_analz_respond]; |
457 |
366 |
458 |
367 |
459 goal thy |
368 goal thy |
460 "!!evs. [| RB : responses i; \ |
369 "!!evs. [| RB : responses evs; \ |
461 \ ALL K I. (Key K : analz (Key``(newK``I) Un H)) = \ |
370 \ ALL K KK. KK <= Compl (range shrK) --> \ |
462 \ (K : newK``I | Key K : analz H) |] \ |
371 \ (Key K : analz (Key``KK Un H)) = \ |
|
372 \ (K : KK | Key K : analz H) |] \ |
463 \ ==> (Key K : analz (insert RB H)) --> \ |
373 \ ==> (Key K : analz (insert RB H)) --> \ |
464 \ (Key K : parts{RB} | Key K : analz H)"; |
374 \ (Key K : parts{RB} | Key K : analz H)"; |
465 be responses.induct 1; |
375 by (etac responses.induct 1); |
466 by (ALLGOALS |
376 by (ALLGOALS |
467 (asm_simp_tac |
377 (asm_simp_tac |
468 (!simpset addsimps [read_instantiate [("H", "?ff``?xx")] parts_insert, |
378 (analz_image_freshK_ss addsimps [resp_analz_image_freshK_lemma]))); |
469 resp_analz_image_newK_lemma, |
379 (*Simplification using two distinct treatments of "image"*) |
470 insert_Key_singleton, insert_Key_image, |
380 by (simp_tac (!simpset addsimps [parts_insert2]) 1); |
471 Un_assoc RS sym, pushKey_newK] |
|
472 setloop split_tac [expand_if]))); |
|
473 (*The "Message" simpset gives the standard treatment of "image"*) |
|
474 by (simp_tac (simpset_of "Message") 1); |
|
475 by (fast_tac (!claset delrules [allE]) 1); |
381 by (fast_tac (!claset delrules [allE]) 1); |
476 qed "resp_analz_insert_lemma"; |
382 qed "resp_analz_insert_lemma"; |
477 |
383 |
478 bind_thm ("resp_analz_insert", |
384 bind_thm ("resp_analz_insert", |
479 raw_analz_image_newK RSN |
385 raw_analz_image_freshK RSN |
480 (2, resp_analz_insert_lemma) RSN(2, rev_mp)); |
386 (2, resp_analz_insert_lemma) RSN(2, rev_mp)); |
481 |
387 |
482 |
388 |
483 (*The Server does not send such messages. This theorem lets us avoid |
389 (*The Server does not send such messages. This theorem lets us avoid |
484 assuming B~=Server in RA4.*) |
390 assuming B~=Server in RA4.*) |
485 goal thy |
391 goal thy |
486 "!!evs. evs : recur lost \ |
392 "!!evs. evs : recur lost \ |
487 \ ==> ALL C X Y P. Says Server C {|X, Agent Server, Agent C, Y, P|} \ |
393 \ ==> ALL C X Y P. Says Server C {|X, Agent Server, Agent C, Y, P|} \ |
488 \ ~: set_of_list evs"; |
394 \ ~: set_of_list evs"; |
489 by (etac recur.induct 1); |
395 by (etac recur.induct 1); |
490 be (respond.induct) 5; |
396 by (etac (respond.induct) 5); |
491 by (Auto_tac()); |
397 by (Auto_tac()); |
492 qed_spec_mp "Says_Server_not"; |
398 qed_spec_mp "Says_Server_not"; |
493 AddSEs [Says_Server_not RSN (2,rev_notE)]; |
399 AddSEs [Says_Server_not RSN (2,rev_notE)]; |
494 |
400 |
495 |
401 |
496 goal thy |
402 (*The last key returned by respond indeed appears in a certificate*) |
497 "!!i. (j,PB,RB) : respond i \ |
403 goal thy |
498 \ ==> EX A' B'. ALL A B N. \ |
404 "!!K. (Hash[Key(shrK A)] {|Agent A, B, NA, P|}, RA, K) : respond evs \ |
|
405 \ ==> Crypt (shrK A) {|Key K, B, NA|} : parts {RA}"; |
|
406 by (etac respond.elim 1); |
|
407 by (ALLGOALS Asm_full_simp_tac); |
|
408 qed "respond_certificate"; |
|
409 |
|
410 |
|
411 goal thy |
|
412 "!!K'. (PB,RB,KXY) : respond evs \ |
|
413 \ ==> EX A' B'. ALL A B N. \ |
499 \ Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB} \ |
414 \ Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB} \ |
500 \ --> (A'=A & B'=B) | (A'=B & B'=A)"; |
415 \ --> (A'=A & B'=B) | (A'=B & B'=A)"; |
501 be respond.induct 1; |
416 by (etac respond.induct 1); |
502 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [all_conj_distrib]))); |
417 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [all_conj_distrib]))); |
503 (*Base case*) |
418 (*Base case*) |
504 by (Fast_tac 1); |
419 by (Fast_tac 1); |
505 by (Step_tac 1); |
420 by (Step_tac 1); |
|
421 (*Case analysis on K=KBC*) |
506 by (expand_case_tac "K = ?y" 1); |
422 by (expand_case_tac "K = ?y" 1); |
|
423 by (dtac respond_Key_in_parts 1); |
507 by (best_tac (!claset addSIs [exI] |
424 by (best_tac (!claset addSIs [exI] |
508 addSEs partsEs |
425 addSEs partsEs |
509 addDs [Key_in_parts_respond] |
426 addDs [Key_in_parts_respond]) 1); |
510 addss (!simpset)) 1); |
427 (*Case analysis on K=KAB*) |
511 by (expand_case_tac "K = ?y" 1); |
428 by (expand_case_tac "K = ?y" 1); |
512 by (REPEAT (ares_tac [exI] 2)); |
429 by (REPEAT (ares_tac [exI] 2)); |
513 by (ex_strip_tac 1); |
430 by (ex_strip_tac 1); |
514 be respond.elim 1; |
431 by (dtac respond_certificate 1); |
515 by (REPEAT_FIRST (etac Pair_inject ORELSE' hyp_subst_tac)); |
|
516 by (ALLGOALS (asm_full_simp_tac |
|
517 (!simpset addsimps [all_conj_distrib, ex_disj_distrib]))); |
|
518 by (Fast_tac 1); |
|
519 by (Fast_tac 1); |
432 by (Fast_tac 1); |
520 val lemma = result(); |
433 val lemma = result(); |
521 |
434 |
522 goal thy |
435 goal thy |
523 "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB}; \ |
436 "!!RB. [| Crypt (shrK A) {|Key K, Agent B, N|} : parts {RB}; \ |
524 \ Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB}; \ |
437 \ Crypt (shrK A') {|Key K, Agent B', N'|} : parts {RB}; \ |
525 \ (j,PB,RB) : respond i |] \ |
438 \ (PB,RB,KXY) : respond evs |] \ |
526 \ ==> (A'=A & B'=B) | (A'=B & B'=A)"; |
439 \ ==> (A'=A & B'=B) | (A'=B & B'=A)"; |
527 by (prove_unique_tac lemma 1); (*50 seconds??, due to the disjunctions*) |
440 by (prove_unique_tac lemma 1); (*50 seconds??, due to the disjunctions*) |
528 qed "unique_session_keys"; |
441 qed "unique_session_keys"; |
529 |
442 |
530 |
443 |
531 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
444 (** Crucial secrecy property: Spy does not see the keys sent in msg RA3 |
532 Does not in itself guarantee security: an attack could violate |
445 Does not in itself guarantee security: an attack could violate |
533 the premises, e.g. by having A=Spy **) |
446 the premises, e.g. by having A=Spy **) |
534 |
447 |
535 goal thy |
448 goal thy |
536 "!!j. (j, HPair (Key(shrK A)) {|Agent A, B, NA, P|}, RA) : respond i \ |
449 "!!evs. [| (PB,RB,KAB) : respond evs; evs : recur lost |] \ |
537 \ ==> Crypt (shrK A) {|Key (newK2 (i,j)), B, NA|} : parts {RA}"; |
|
538 be respond.elim 1; |
|
539 by (ALLGOALS Asm_full_simp_tac); |
|
540 qed "newK2_respond_lemma"; |
|
541 |
|
542 |
|
543 goal thy |
|
544 "!!evs. [| (j,PB,RB) : respond (length evs); evs : recur lost |] \ |
|
545 \ ==> ALL A A' N. A ~: lost & A' ~: lost --> \ |
450 \ ==> ALL A A' N. A ~: lost & A' ~: lost --> \ |
546 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
451 \ Crypt (shrK A) {|Key K, Agent A', N|} : parts{RB} --> \ |
547 \ Key K ~: analz (insert RB (sees lost Spy evs))"; |
452 \ Key K ~: analz (insert RB (sees lost Spy evs))"; |
548 be respond.induct 1; |
453 by (etac respond.induct 1); |
549 by (forward_tac [respond_imp_responses] 2); |
454 by (forward_tac [respond_imp_responses] 2); |
550 by (ALLGOALS (*4 MINUTES???*) |
455 by (forward_tac [respond_imp_not_used] 2); |
|
456 by (ALLGOALS (*43 seconds*) |
551 (asm_simp_tac |
457 (asm_simp_tac |
552 (!simpset addsimps |
458 (analz_image_freshK_ss addsimps |
553 ([analz_image_newK, not_parts_not_analz, |
459 [analz_image_freshK, not_parts_not_analz, |
554 read_instantiate [("H", "?ff``?xx")] parts_insert, |
460 shrK_in_analz_respond, |
555 Un_assoc RS sym, resp_analz_image_newK, |
461 read_instantiate [("H", "?ff``?xx")] parts_insert, |
556 insert_Key_singleton, analz_insert_Key_newK]) |
462 resp_analz_image_freshK, analz_insert_freshK]))); |
557 setloop split_tac [expand_if]))); |
463 by (ALLGOALS Simp_tac); |
558 by (ALLGOALS (simp_tac (simpset_of "Message"))); |
464 by (fast_tac (!claset addIs [impOfSubs analz_subset_parts]) 1); |
559 by (Fast_tac 1); |
|
560 by (step_tac (!claset addSEs [MPair_parts]) 1); |
465 by (step_tac (!claset addSEs [MPair_parts]) 1); |
561 (** LEVEL 6 **) |
466 (** LEVEL 7 **) |
562 by (fast_tac (!claset addDs [resp_analz_insert, Key_in_parts_respond] |
467 by (fast_tac (!claset addSDs [resp_analz_insert, Key_in_parts_respond] |
563 addSEs [new_keys_not_seen RS not_parts_not_analz |
468 addDs [impOfSubs analz_subset_parts]) 4); |
564 RSN(2,rev_notE)] |
469 by (fast_tac (!claset addSDs [respond_certificate]) 3); |
565 addss (!simpset)) 4); |
|
566 by (fast_tac (!claset addSDs [newK2_respond_lemma]) 3); |
|
567 by (best_tac (!claset addSEs partsEs |
470 by (best_tac (!claset addSEs partsEs |
568 addDs [Key_in_parts_respond] |
471 addDs [Key_in_parts_respond] |
569 addss (!simpset)) 2); |
472 addss (!simpset)) 2); |
570 by (thin_tac "ALL x.?P(x)" 1); |
473 by (dtac unique_session_keys 1); |
571 be respond.elim 1; |
474 by (etac respond_certificate 1); |
572 by (fast_tac (!claset addss (!simpset)) 1); |
475 by (assume_tac 1); |
573 by (step_tac (!claset addss (!simpset)) 1); |
476 by (Fast_tac 1); |
574 by (best_tac (!claset addSEs partsEs |
|
575 addDs [Key_in_parts_respond] |
|
576 addss (!simpset)) 1); |
|
577 qed_spec_mp "respond_Spy_not_see_encrypted_key"; |
477 qed_spec_mp "respond_Spy_not_see_encrypted_key"; |
578 |
478 |
579 |
479 |
580 goal thy |
480 goal thy |
581 "!!evs. [| A ~: lost; A' ~: lost; evs : recur lost |] \ |
481 "!!evs. [| A ~: lost; A' ~: lost; evs : recur lost |] \ |
620 |
521 |
621 |
522 |
622 (**** Authenticity properties for Agents ****) |
523 (**** Authenticity properties for Agents ****) |
623 |
524 |
624 (*The response never contains Hashes*) |
525 (*The response never contains Hashes*) |
625 (*NEEDED????????????????*) |
526 goal thy |
626 goal thy |
527 "!!evs. (PB,RB,K) : respond evs \ |
627 "!!evs. (j,PB,RB) : respond i \ |
|
628 \ ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \ |
528 \ ==> Hash {|Key (shrK B), M|} : parts (insert RB H) --> \ |
629 \ Hash {|Key (shrK B), M|} : parts H"; |
529 \ Hash {|Key (shrK B), M|} : parts H"; |
630 be (respond_imp_responses RS responses.induct) 1; |
530 by (etac (respond_imp_responses RS responses.induct) 1); |
631 by (Auto_tac()); |
531 by (Auto_tac()); |
632 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp)); |
532 bind_thm ("Hash_in_parts_respond", result() RSN (2, rev_mp)); |
633 |
533 |
634 (*NEEDED????????????????*) |
|
635 (*Only RA1 or RA2 can have caused such a part of a message to appear.*) |
534 (*Only RA1 or RA2 can have caused such a part of a message to appear.*) |
636 goalw thy [HPair_def] |
535 goalw thy [HPair_def] |
637 "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|} \ |
536 "!!evs. [| Hash {|Key(shrK A), Agent A, Agent B, NA, P|} \ |
638 \ : parts (sees lost Spy evs); \ |
537 \ : parts (sees lost Spy evs); \ |
639 \ A ~: lost; evs : recur lost |] \ |
538 \ A ~: lost; evs : recur lost |] \ |
640 \ ==> Says A B (HPair (Key(shrK A)) {|Agent A, Agent B, NA, P|}) \ |
539 \ ==> Says A B (Hash[Key(shrK A)] {|Agent A, Agent B, NA, P|}) \ |
641 \ : set_of_list evs"; |
540 \ : set_of_list evs"; |
642 be rev_mp 1; |
541 by (etac rev_mp 1); |
643 by (parts_induct_tac 1); |
542 by (parts_induct_tac 1); |
644 (*RA3*) |
543 (*RA3*) |
645 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 1); |
544 by (fast_tac (!claset addSDs [Hash_in_parts_respond]) 1); |
646 qed_spec_mp "Hash_auth_sender"; |
545 qed_spec_mp "Hash_auth_sender"; |
647 |
546 |
648 |
547 |
649 val nonce_not_seen_now = le_refl RSN (2, new_nonces_not_seen) RSN (2,rev_notE); |
548 (** These two results subsume (for all agents) the guarantees proved |
650 |
|
651 |
|
652 (** These two results should subsume (for all agents) the guarantees proved |
|
653 separately for A and B in the Otway-Rees protocol. |
549 separately for A and B in the Otway-Rees protocol. |
654 **) |
550 **) |
655 |
551 |
656 |
552 |
657 (*Encrypted messages can only originate with the Server.*) |
553 (*Encrypted messages can only originate with the Server.*) |