95 (**** Protocol Proofs ****) |
95 (**** Protocol Proofs ****) |
96 |
96 |
97 (*A "possibility property": there are traces that reach the end. |
97 (*A "possibility property": there are traces that reach the end. |
98 This protocol has three end points and six messages to consider.*) |
98 This protocol has three end points and six messages to consider.*) |
99 |
99 |
|
100 |
|
101 (** These proofs make the further assumption that the Nonce_supply nonces |
|
102 (which have the form @ N. Nonce N ~: used evs) |
|
103 lie outside the range of PRF. This assumption seems reasonable, but |
|
104 as it is needed only for the possibility theorems, it is not taken |
|
105 as an axiom. |
|
106 **) |
|
107 |
|
108 |
|
109 |
100 (*Possibility property ending with ServerFinished.*) |
110 (*Possibility property ending with ServerFinished.*) |
101 goal thy |
111 goal thy |
102 "!!A B. A ~= B ==> EX NA XA NB XB M. EX evs: tls. \ |
112 "!!A B. [| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF; \ |
103 \ Says B A (Crypt (serverK(NA,NB,M)) \ |
113 \ A ~= B |] ==> EX NA XA NB XB M. EX evs: tls. \ |
104 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
114 \ Says B A (Crypt (serverK(NA,NB,M)) \ |
105 \ Nonce NA, Agent XA, Agent A, \ |
115 \ (Hash{|Nonce M, Nonce NA, Number XA, Agent A, \ |
106 \ Nonce NB, Agent XB, \ |
116 \ Nonce NB, Number XB, Agent B|})) \ |
107 \ certificate B (pubK B)|})) \ |
|
108 \ : set evs"; |
117 \ : set evs"; |
109 by (REPEAT (resolve_tac [exI,bexI] 1)); |
118 by (REPEAT (resolve_tac [exI,bexI] 1)); |
110 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
119 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
111 RS tls.ServerFinished) 2); |
120 RS tls.ServerFinished) 2); |
112 by possibility_tac; |
121 by possibility_tac; |
|
122 by (REPEAT (Blast_tac 1)); |
113 result(); |
123 result(); |
114 |
124 |
115 (*And one for ClientFinished. Either FINISHED message may come first.*) |
125 (*And one for ClientFinished. Either FINISHED message may come first.*) |
116 goal thy |
126 goal thy |
117 "!!A B. A ~= B ==> EX NA XA NB XB M. EX evs: tls. \ |
127 "!!A B. [| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF; \ |
|
128 \ A ~= B |] ==> EX NA XA NB XB M. EX evs: tls. \ |
118 \ Says A B (Crypt (clientK(NA,NB,M)) \ |
129 \ Says A B (Crypt (clientK(NA,NB,M)) \ |
119 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
130 \ (Hash{|Nonce M, Nonce NA, Number XA, Agent A, \ |
120 \ Nonce NA, Agent XA, certificate A (pubK A), \ |
131 \ Nonce NB, Number XB, Agent B|})) : set evs"; |
121 \ Nonce NB, Agent XB, Agent B|})) : set evs"; |
|
122 by (REPEAT (resolve_tac [exI,bexI] 1)); |
132 by (REPEAT (resolve_tac [exI,bexI] 1)); |
123 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
133 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
124 RS tls.ClientFinished) 2); |
134 RS tls.ClientFinished) 2); |
125 by possibility_tac; |
135 by possibility_tac; |
|
136 by (REPEAT (Blast_tac 1)); |
126 result(); |
137 result(); |
127 |
138 |
128 (*Another one, for CertVerify (which is optional)*) |
139 (*Another one, for CertVerify (which is optional)*) |
129 goal thy |
140 goal thy |
130 "!!A B. A ~= B ==> EX NB M. EX evs: tls. \ |
141 "!!A B. [| ALL evs. (@ N. Nonce N ~: used evs) ~: range PRF; \ |
|
142 \ A ~= B |] ==> EX NB PMS. EX evs: tls. \ |
131 \ Says A B (Crypt (priK A) \ |
143 \ Says A B (Crypt (priK A) \ |
132 \ (Hash{|Nonce NB, certificate B (pubK B), Nonce M|})) : set evs"; |
144 \ (Hash{|Nonce NB, certificate B (pubK B), Nonce PMS|})) : set evs"; |
133 by (REPEAT (resolve_tac [exI,bexI] 1)); |
145 by (REPEAT (resolve_tac [exI,bexI] 1)); |
134 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
146 by (rtac (tls.Nil RS tls.ClientHello RS tls.ServerHello RS tls.ClientCertKeyEx |
135 RS tls.CertVerify) 2); |
147 RS tls.CertVerify) 2); |
136 by possibility_tac; |
148 by possibility_tac; |
|
149 by (REPEAT (Blast_tac 1)); |
137 result(); |
150 result(); |
138 |
151 |
139 |
152 |
140 (**** Inductive proofs about tls ****) |
153 (**** Inductive proofs about tls ****) |
141 |
154 |
209 etac tls.induct i THEN |
222 etac tls.induct i THEN |
210 ClientCertKeyEx_tac (i+7) THEN (*ClientFinished*) |
223 ClientCertKeyEx_tac (i+7) THEN (*ClientFinished*) |
211 ClientCertKeyEx_tac (i+6) THEN (*CertVerify*) |
224 ClientCertKeyEx_tac (i+6) THEN (*CertVerify*) |
212 ClientCertKeyEx_tac (i+5) THEN (*ClientCertKeyEx*) |
225 ClientCertKeyEx_tac (i+5) THEN (*ClientCertKeyEx*) |
213 ALLGOALS (asm_simp_tac |
226 ALLGOALS (asm_simp_tac |
214 (!simpset addsimps [not_parts_not_analz] |
227 (!simpset addcongs [if_weak_cong] |
215 setloop split_tac [expand_if])) THEN |
228 setloop split_tac [expand_if])) THEN |
216 (*Remove instances of pubK B: the Spy already knows all public keys. |
229 (*Remove instances of pubK B: the Spy already knows all public keys. |
217 Combining the two simplifier calls makes them run extremely slowly.*) |
230 Combining the two simplifier calls makes them run extremely slowly.*) |
218 ALLGOALS (asm_simp_tac |
231 ALLGOALS (asm_simp_tac |
219 (!simpset addsimps [insert_absorb] |
232 (!simpset addcongs [if_weak_cong] |
|
233 addsimps [insert_absorb] |
220 setloop split_tac [expand_if])); |
234 setloop split_tac [expand_if])); |
221 |
235 |
222 |
236 |
223 (*** Hashing of nonces ***) |
237 (*** Hashing of nonces ***) |
224 |
238 |
225 (*Every Nonce that's hashed is already in past traffic. *) |
239 (*Every Nonce that's hashed is already in past traffic. |
226 goal thy "!!evs. [| Hash {|Nonce N, X|} : parts (sees Spy evs); \ |
240 This event occurs in CERTIFICATE VERIFY*) |
227 \ evs : tls |] \ |
241 goal thy "!!evs. [| Hash {|Nonce NB, X|} : parts (sees Spy evs); \ |
228 \ ==> Nonce N : parts (sees Spy evs)"; |
242 \ NB ~: range PRF; evs : tls |] \ |
|
243 \ ==> Nonce NB : parts (sees Spy evs)"; |
|
244 by (etac rev_mp 1); |
229 by (etac rev_mp 1); |
245 by (etac rev_mp 1); |
230 by (parts_induct_tac 1); |
246 by (parts_induct_tac 1); |
231 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
247 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
232 by (Fake_parts_insert_tac 1); |
248 by (Fake_parts_insert_tac 1); |
233 by (blast_tac (!claset addSDs [Says_imp_sees_Spy RS parts.Inj] |
249 (*FINISHED messages are trivial because M : range PRF*) |
234 addSEs partsEs) 1); |
250 by (REPEAT (Blast_tac 2)); |
235 qed "Hash_imp_Nonce1"; |
251 (*CERTIFICATE VERIFY is the only interesting case*) |
236 |
252 by (blast_tac (!claset addSEs sees_Spy_partsEs) 1); |
237 (*Lemma needed to prove Hash_Hash_imp_Nonce*) |
253 qed "Hash_Nonce_CV"; |
238 goal thy "!!evs. [| Hash{|Nonce NA, Nonce NB, Nonce M|} \ |
|
239 \ : parts (sees Spy evs); \ |
|
240 \ evs : tls |] \ |
|
241 \ ==> Nonce M : parts (sees Spy evs)"; |
|
242 by (etac rev_mp 1); |
|
243 by (parts_induct_tac 1); |
|
244 by (asm_simp_tac (!simpset addsimps [parts_insert_sees]) 1); |
|
245 by (Fake_parts_insert_tac 1); |
|
246 qed "Hash_imp_Nonce2"; |
|
247 AddSDs [Hash_imp_Nonce2]; |
|
248 |
254 |
249 |
255 |
250 goal thy "!!evs. [| Notes A {|Agent B, X|} : set evs; evs : tls |] \ |
256 goal thy "!!evs. [| Notes A {|Agent B, X|} : set evs; evs : tls |] \ |
251 \ ==> Crypt (pubK B) X : parts (sees Spy evs)"; |
257 \ ==> Crypt (pubK B) X : parts (sees Spy evs)"; |
252 by (etac rev_mp 1); |
258 by (etac rev_mp 1); |
253 by (analz_induct_tac 1); |
259 by (analz_induct_tac 1); |
254 by (blast_tac (!claset addIs [parts_insertI]) 1); |
260 by (blast_tac (!claset addIs [parts_insertI]) 1); |
255 qed "Notes_Crypt_parts_sees"; |
261 qed "Notes_Crypt_parts_sees"; |
256 |
262 |
257 |
263 |
258 (*NEEDED??*) |
264 (***************** |
259 goal thy "!!evs. [| Hash {| Hash{|Nonce NA, Nonce NB, Nonce M|}, X |} \ |
265 (*NEEDED? TRUE??? |
260 \ : parts (sees Spy evs); \ |
266 Every Nonce that's hashed is already in past traffic. |
261 \ evs : tls |] \ |
267 This general formulation is tricky to prove and hard to use, since the |
262 \ ==> Nonce M : parts (sees Spy evs)"; |
268 2nd premise is typically proved by simplification.*) |
263 by (etac rev_mp 1); |
269 goal thy "!!evs. [| Hash X : parts (sees Spy evs); \ |
264 by (parts_induct_tac 1); |
270 \ Nonce N : parts {X}; evs : tls |] \ |
265 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
271 \ ==> Nonce N : parts (sees Spy evs)"; |
266 by (Fake_parts_insert_tac 1); |
272 by (etac rev_mp 1); |
267 by (REPEAT (blast_tac (!claset addSDs [Notes_Crypt_parts_sees, |
273 by (parts_induct_tac 1); |
268 Says_imp_sees_Spy RS parts.Inj] |
274 by (step_tac (!claset addSDs [Notes_Crypt_parts_sees, |
269 addSEs partsEs) 1)); |
275 Says_imp_sees_Spy RS parts.Inj] |
270 qed "Hash_Hash_imp_Nonce"; |
276 addSEs partsEs) 1); |
271 |
277 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [parts_insert_sees]))); |
272 |
278 by (Fake_parts_insert_tac 1); |
273 (*NEEDED?? |
279 (*CertVerify, ClientFinished, ServerFinished (?)*) |
274 Every Nonce that's hashed is already in past traffic. |
280 by (REPEAT (Blast_tac 1)); |
275 This general formulation is tricky to prove and hard to use, since the |
281 qed "Hash_imp_Nonce_seen"; |
276 2nd premise is typically proved by simplification.*) |
282 ****************************************************************) |
277 goal thy "!!evs. [| Hash X : parts (sees Spy evs); \ |
|
278 \ Nonce N : parts {X}; evs : tls |] \ |
|
279 \ ==> Nonce N : parts (sees Spy evs)"; |
|
280 by (etac rev_mp 1); |
|
281 by (parts_induct_tac 1); |
|
282 by (step_tac (!claset addSDs [Notes_Crypt_parts_sees, |
|
283 Says_imp_sees_Spy RS parts.Inj] |
|
284 addSEs partsEs) 1); |
|
285 by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [parts_insert_sees]))); |
|
286 by (Fake_parts_insert_tac 1); |
|
287 (*CertVerify, ClientFinished, ServerFinished (?)*) |
|
288 by (REPEAT (Blast_tac 1)); |
|
289 qed "Hash_imp_Nonce_seen"; |
|
290 |
283 |
291 |
284 |
292 (*** Protocol goal: if B receives CERTIFICATE VERIFY, then A sent it ***) |
285 (*** Protocol goal: if B receives CERTIFICATE VERIFY, then A sent it ***) |
293 |
286 |
294 (*B can check A's signature if he has received A's certificate. |
287 (*B can check A's signature if he has received A's certificate. |
295 Perhaps B~=Spy is unnecessary, but there's no obvious proof if the first |
288 Perhaps B~=Spy is unnecessary, but there's no obvious proof if the first |
296 message is Fake. We don't need guarantees for the Spy anyway. We must |
289 message is Fake. We don't need guarantees for the Spy anyway. We must |
297 assume A~:lost; otherwise, the Spy can forge A's signature.*) |
290 assume A~:lost; otherwise, the Spy can forge A's signature.*) |
298 goal thy |
291 goal thy |
299 "!!evs. [| X = Crypt (priK A) \ |
292 "!!evs. [| X = Crypt (priK A) \ |
300 \ (Hash{|Nonce NB, certificate B KB, Nonce M|}); \ |
293 \ (Hash{|Nonce NB, certificate B KB, Nonce PMS|}); \ |
301 \ evs : tls; A ~: lost; B ~= Spy |] \ |
294 \ evs : tls; A ~: lost; B ~= Spy |] \ |
302 \ ==> Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
295 \ ==> Says B A {|Nonce NA, Nonce NB, Number XB, certificate B KB|} \ |
303 \ : set evs --> \ |
296 \ : set evs --> \ |
304 \ X : parts (sees Spy evs) --> Says A B X : set evs"; |
297 \ X : parts (sees Spy evs) --> Says A B X : set evs"; |
305 by (hyp_subst_tac 1); |
298 by (hyp_subst_tac 1); |
306 by (parts_induct_tac 1); |
299 by (parts_induct_tac 1); |
307 by (Fake_parts_insert_tac 1); |
300 by (Fake_parts_insert_tac 1); |
308 (*ServerHello: nonce NB cannot be in X because it's fresh!*) |
301 (*ServerHello: nonce NB cannot be in X because it's fresh!*) |
309 by (blast_tac (!claset addSDs [Hash_imp_Nonce1] |
302 by (blast_tac (!claset addSDs [Hash_Nonce_CV] |
310 addSEs sees_Spy_partsEs) 1); |
303 addSEs sees_Spy_partsEs) 1); |
311 qed_spec_mp "TrustCertVerify"; |
304 qed_spec_mp "TrustCertVerify"; |
312 |
305 |
313 |
306 |
314 (*If CERTIFICATE VERIFY is present then A has chosen M.*) |
307 (*If CERTIFICATE VERIFY is present then A has chosen PMS.*) |
315 goal thy |
308 goal thy |
316 "!!evs. [| Crypt (priK A) (Hash{|Nonce NB, certificate B KB, Nonce M|}) \ |
309 "!!evs. [| Crypt (priK A) (Hash{|Nonce NB, certificate B KB, Nonce PMS|}) \ |
317 \ : parts (sees Spy evs); \ |
310 \ : parts (sees Spy evs); \ |
318 \ evs : tls; A ~: lost |] \ |
311 \ evs : tls; A ~: lost |] \ |
319 \ ==> Notes A {|Agent B, Nonce M|} : set evs"; |
312 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs"; |
320 be rev_mp 1; |
313 be rev_mp 1; |
321 by (parts_induct_tac 1); |
314 by (parts_induct_tac 1); |
322 by (Fake_parts_insert_tac 1); |
315 by (Fake_parts_insert_tac 1); |
323 qed "UseCertVerify"; |
316 qed "UseCertVerify"; |
324 |
317 |
354 \ (Nonce N : analz (sees Spy evs))"; |
347 \ (Nonce N : analz (sees Spy evs))"; |
355 by (etac tls.induct 1); |
348 by (etac tls.induct 1); |
356 by (ClientCertKeyEx_tac 6); |
349 by (ClientCertKeyEx_tac 6); |
357 by (REPEAT_FIRST (resolve_tac [allI, impI])); |
350 by (REPEAT_FIRST (resolve_tac [allI, impI])); |
358 by (REPEAT_FIRST (rtac lemma)); |
351 by (REPEAT_FIRST (rtac lemma)); |
359 writeln"SLOW simplification: 50 secs!??"; |
352 writeln"SLOW simplification: 60 secs!??"; |
360 by (ALLGOALS |
353 by (ALLGOALS |
361 (asm_simp_tac (analz_image_keys_ss |
354 (asm_simp_tac (analz_image_keys_ss |
362 addsimps (analz_image_priK::certificate_def:: |
355 addsimps (analz_image_priK::certificate_def:: |
363 keys_distinct)))); |
356 keys_distinct)))); |
364 by (ALLGOALS (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_priK]))); |
|
365 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb]))); |
357 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb]))); |
366 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*) |
358 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*) |
367 by (Blast_tac 3); |
359 by (Blast_tac 3); |
368 (*Fake*) |
360 (*Fake*) |
369 by (spy_analz_tac 2); |
361 by (spy_analz_tac 2); |
370 (*Base*) |
362 (*Base*) |
371 by (Blast_tac 1); |
363 by (Blast_tac 1); |
372 qed_spec_mp "analz_image_keys"; |
364 qed_spec_mp "analz_image_keys"; |
373 |
365 |
374 |
366 |
375 (*If A sends ClientCertKeyEx to an uncompromised B, then M will stay secret.*) |
367 goal thy "!!evs. evs : tls ==> Notes A {|Agent B, Nonce (PRF x)|} ~: set evs"; |
|
368 by (parts_induct_tac 1); |
|
369 (*ClientCertKeyEx: PMS is assumed to differ from any PRF.*) |
|
370 by (Blast_tac 1); |
|
371 qed "no_Notes_A_PRF"; |
|
372 Addsimps [no_Notes_A_PRF]; |
|
373 |
|
374 |
|
375 (*If A sends ClientCertKeyEx to an honest B, then the PMS will stay secret.*) |
376 goal thy |
376 goal thy |
377 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
377 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
378 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
378 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \ |
379 \ Nonce M ~: analz (sees Spy evs)"; |
379 \ Nonce PMS ~: analz (sees Spy evs)"; |
380 by (analz_induct_tac 1); |
380 by (analz_induct_tac 1); (*47 seconds???*) |
381 (*ClientHello*) |
381 (*ClientHello*) |
382 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
382 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
383 addSEs sees_Spy_partsEs) 3); |
383 addSEs sees_Spy_partsEs) 3); |
384 (*SpyKeys*) |
384 (*SpyKeys*) |
385 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2); |
385 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2); |
|
386 by (fast_tac (!claset addss (!simpset)) 2); |
386 (*Fake*) |
387 (*Fake*) |
387 by (spy_analz_tac 1); |
388 by (spy_analz_tac 1); |
388 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*) |
389 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*) |
389 by (REPEAT (blast_tac (!claset addSEs partsEs |
390 by (REPEAT (blast_tac (!claset addSEs partsEs |
390 addDs [Notes_Crypt_parts_sees, |
391 addDs [Notes_Crypt_parts_sees, |
391 impOfSubs analz_subset_parts, |
392 impOfSubs analz_subset_parts, |
392 Says_imp_sees_Spy RS analz.Inj]) 1)); |
393 Says_imp_sees_Spy RS analz.Inj]) 1)); |
393 bind_thm ("Spy_not_see_premaster_secret", result() RSN (2, rev_mp)); |
394 bind_thm ("Spy_not_see_PMS", result() RSN (2, rev_mp)); |
|
395 |
|
396 |
|
397 |
|
398 goal thy "!!evs. [| Nonce (PRF (PMS,NA,NB)) : parts (sees Spy evs); \ |
|
399 \ evs : tls |] \ |
|
400 \ ==> Nonce PMS : parts (sees Spy evs)"; |
|
401 by (etac rev_mp 1); |
|
402 by (parts_induct_tac 1); |
|
403 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
|
404 by (Fake_parts_insert_tac 1); |
|
405 (*Client key exchange*) |
|
406 by (Blast_tac 4); |
|
407 (*Server Hello: by freshness*) |
|
408 by (blast_tac (!claset addSEs sees_Spy_partsEs) 3); |
|
409 (*Client Hello: trivial*) |
|
410 by (Blast_tac 2); |
|
411 (*SpyKeys*) |
|
412 by (blast_tac (!claset addSEs sees_Spy_partsEs) 1); |
|
413 qed "MS_imp_PMS"; |
|
414 AddSDs [MS_imp_PMS]; |
|
415 |
|
416 |
|
417 (*If A sends ClientCertKeyEx to an honest B, then the MASTER SECRET |
|
418 will stay secret.*) |
|
419 goal thy |
|
420 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
|
421 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \ |
|
422 \ Nonce (PRF(PMS,NA,NB)) ~: analz (sees Spy evs)"; |
|
423 by (analz_induct_tac 1); (*47 seconds???*) |
|
424 (*ClientHello*) |
|
425 by (Blast_tac 3); |
|
426 (*SpyKeys: by secrecy of the PMS, Spy cannot make the MS*) |
|
427 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2); |
|
428 by (blast_tac (!claset addSDs [Spy_not_see_PMS, |
|
429 Says_imp_sees_Spy RS analz.Inj]) 2); |
|
430 (*Fake*) |
|
431 by (spy_analz_tac 1); |
|
432 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*) |
|
433 by (REPEAT (blast_tac (!claset addSEs partsEs |
|
434 addDs [MS_imp_PMS, |
|
435 Notes_Crypt_parts_sees, |
|
436 impOfSubs analz_subset_parts, |
|
437 Says_imp_sees_Spy RS analz.Inj]) 1)); |
|
438 bind_thm ("Spy_not_see_MS", result() RSN (2, rev_mp)); |
|
439 |
394 |
440 |
395 |
441 |
396 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***) |
442 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***) |
397 |
443 |
398 (** First, some lemmas about those write keys. The proofs for serverK are |
444 (** First, some lemmas about those write keys. The proofs for serverK are |
399 nearly identical to those for clientK. **) |
445 nearly identical to those for clientK. **) |
400 |
446 |
401 (*Lemma: those write keys are never sent if M is secure. |
447 (*Lemma: those write keys are never sent if M (MASTER SECRET) is secure. |
402 Converse doesn't hold; betraying M doesn't force the keys to be sent!*) |
448 Converse doesn't hold; betraying M doesn't force the keys to be sent!*) |
403 |
449 |
404 goal thy |
450 goal thy |
405 "!!evs. [| Nonce M ~: analz (sees Spy evs); evs : tls |] \ |
451 "!!evs. [| Nonce M ~: analz (sees Spy evs); evs : tls |] \ |
406 \ ==> Key (clientK(NA,NB,M)) ~: parts (sees Spy evs)"; |
452 \ ==> Key (clientK(NA,NB,M)) ~: parts (sees Spy evs)"; |
429 (*Fake*) |
476 (*Fake*) |
430 by (spy_analz_tac 2); |
477 by (spy_analz_tac 2); |
431 (*Base*) |
478 (*Base*) |
432 by (Blast_tac 1); |
479 by (Blast_tac 1); |
433 qed "serverK_notin_parts"; |
480 qed "serverK_notin_parts"; |
434 |
481 bind_thm ("serverK_in_partsE", serverK_notin_parts RSN (2, rev_notE)); |
435 Addsimps [serverK_notin_parts]; |
482 Addsimps [serverK_notin_parts]; |
436 AddSEs [serverK_notin_parts RSN (2, rev_notE)]; |
483 AddSEs [serverK_in_partsE, |
437 |
484 impOfSubs analz_subset_parts RS serverK_in_partsE]; |
438 (*Lemma: those write keys are never used if M is fresh. |
485 |
439 Converse doesn't hold; betraying M doesn't force the keys to be sent! |
486 |
440 NOT suitable as safe elim rules.*) |
487 (*Lemma: those write keys are never used if PMS is fresh. |
441 |
488 Nonces don't have to agree, allowing session resumption. |
442 goal thy |
489 Converse doesn't hold; revealing PMS doesn't force the keys to be sent. |
443 "!!evs. [| Nonce M ~: used evs; evs : tls |] \ |
490 They are NOT suitable as safe elim rules.*) |
444 \ ==> Crypt (clientK(NA,NB,M)) Y ~: parts (sees Spy evs)"; |
491 |
|
492 goal thy |
|
493 "!!evs. [| Nonce PMS ~: used evs; evs : tls |] \ |
|
494 \ ==> Crypt (clientK(Na, Nb, PRF(PMS,NA,NB))) Y ~: parts (sees Spy evs)"; |
445 by (etac rev_mp 1); |
495 by (etac rev_mp 1); |
446 by (analz_induct_tac 1); |
496 by (analz_induct_tac 1); |
447 (*ClientFinished: since M is fresh, a different instance of clientK was used.*) |
497 (*ClientFinished: since M is fresh, a different instance of clientK was used.*) |
448 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
498 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
449 addSEs sees_Spy_partsEs) 3); |
499 addSEs sees_Spy_partsEs) 3); |
450 by (Fake_parts_insert_tac 2); |
500 by (Fake_parts_insert_tac 2); |
451 (*Base*) |
501 (*Base*) |
452 by (Blast_tac 1); |
502 by (Blast_tac 1); |
453 qed "Crypt_clientK_notin_parts"; |
503 qed "Crypt_clientK_notin_parts"; |
454 |
|
455 Addsimps [Crypt_clientK_notin_parts]; |
504 Addsimps [Crypt_clientK_notin_parts]; |
456 AddEs [Crypt_clientK_notin_parts RSN (2, rev_notE)]; |
505 AddEs [Crypt_clientK_notin_parts RSN (2, rev_notE)]; |
457 |
506 |
458 goal thy |
507 goal thy |
459 "!!evs. [| Nonce M ~: used evs; evs : tls |] \ |
508 "!!evs. [| Nonce PMS ~: used evs; evs : tls |] \ |
460 \ ==> Crypt (serverK(NA,NB,M)) Y ~: parts (sees Spy evs)"; |
509 \ ==> Crypt (serverK(Na, Nb, PRF(PMS,NA,NB))) Y ~: parts (sees Spy evs)"; |
461 by (etac rev_mp 1); |
510 by (etac rev_mp 1); |
462 by (analz_induct_tac 1); |
511 by (analz_induct_tac 1); |
463 (*ServerFinished: since M is fresh, a different instance of serverK was used.*) |
512 (*ServerFinished: since M is fresh, a different instance of serverK was used.*) |
464 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
513 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
465 addSEs sees_Spy_partsEs) 3); |
514 addSEs sees_Spy_partsEs) 3); |
479 be rev_mp 1; |
528 be rev_mp 1; |
480 by (analz_induct_tac 1); |
529 by (analz_induct_tac 1); |
481 qed "A_Crypt_pubB"; |
530 qed "A_Crypt_pubB"; |
482 |
531 |
483 |
532 |
484 (*** Unicity results for M, the pre-master-secret ***) |
533 (*** Unicity results for PMS, the pre-master-secret ***) |
485 |
534 |
486 (*M determines B. Proof borrowed from NS_Public/unique_NA and from Yahalom*) |
535 (*PMS determines B. Proof borrowed from NS_Public/unique_NA and from Yahalom*) |
487 goal thy |
536 goal thy |
488 "!!evs. [| Nonce M ~: analz (sees Spy evs); evs : tls |] \ |
537 "!!evs. [| Nonce PMS ~: analz (sees Spy evs); evs : tls |] \ |
489 \ ==> EX B'. ALL B. \ |
538 \ ==> EX B'. ALL B. \ |
490 \ Crypt (pubK B) (Nonce M) : parts (sees Spy evs) --> B=B'"; |
539 \ Crypt (pubK B) (Nonce PMS) : parts (sees Spy evs) --> B=B'"; |
491 by (etac rev_mp 1); |
540 by (etac rev_mp 1); |
492 by (parts_induct_tac 1); |
541 by (parts_induct_tac 1); |
493 by (Fake_parts_insert_tac 1); |
542 by (Fake_parts_insert_tac 1); |
494 (*ClientCertKeyEx*) |
543 (*ClientCertKeyEx*) |
495 by (ClientCertKeyEx_tac 1); |
544 by (ClientCertKeyEx_tac 1); |
496 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1); |
545 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1); |
497 by (expand_case_tac "M = ?y" 1 THEN |
546 by (expand_case_tac "PMS = ?y" 1 THEN |
498 blast_tac (!claset addSEs partsEs) 1); |
547 blast_tac (!claset addSEs partsEs) 1); |
499 val lemma = result(); |
548 val lemma = result(); |
500 |
549 |
501 goal thy |
550 goal thy |
502 "!!evs. [| Crypt(pubK B) (Nonce M) : parts (sees Spy evs); \ |
551 "!!evs. [| Crypt(pubK B) (Nonce PMS) : parts (sees Spy evs); \ |
503 \ Crypt(pubK B') (Nonce M) : parts (sees Spy evs); \ |
552 \ Crypt(pubK B') (Nonce PMS) : parts (sees Spy evs); \ |
504 \ Nonce M ~: analz (sees Spy evs); \ |
553 \ Nonce PMS ~: analz (sees Spy evs); \ |
505 \ evs : tls |] \ |
554 \ evs : tls |] \ |
506 \ ==> B=B'"; |
555 \ ==> B=B'"; |
507 by (prove_unique_tac lemma 1); |
556 by (prove_unique_tac lemma 1); |
508 qed "unique_M"; |
557 qed "unique_PMS"; |
509 |
558 |
510 |
559 |
511 (*In A's note to herself, M determines A and B.*) |
560 (*In A's note to herself, PMS determines A and B.*) |
512 goal thy |
561 goal thy |
513 "!!evs. [| Nonce M ~: analz (sees Spy evs); evs : tls |] \ |
562 "!!evs. [| Nonce PMS ~: analz (sees Spy evs); evs : tls |] \ |
514 \ ==> EX A' B'. ALL A B. \ |
563 \ ==> EX A' B'. ALL A B. \ |
515 \ Notes A {|Agent B, Nonce M|} : set evs --> A=A' & B=B'"; |
564 \ Notes A {|Agent B, Nonce PMS|} : set evs --> A=A' & B=B'"; |
516 by (etac rev_mp 1); |
565 by (etac rev_mp 1); |
517 by (parts_induct_tac 1); |
566 by (parts_induct_tac 1); |
518 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1); |
567 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1); |
519 (*ClientCertKeyEx: if M is fresh, then it can't appear in Notes A X.*) |
568 (*ClientCertKeyEx: if PMS is fresh, then it can't appear in Notes A X.*) |
520 by (expand_case_tac "M = ?y" 1 THEN |
569 by (expand_case_tac "PMS = ?y" 1 THEN |
521 blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1); |
570 blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1); |
522 val lemma = result(); |
571 val lemma = result(); |
523 |
572 |
524 goal thy |
573 goal thy |
525 "!!evs. [| Notes A {|Agent B, Nonce M|} : set evs; \ |
574 "!!evs. [| Notes A {|Agent B, Nonce PMS|} : set evs; \ |
526 \ Notes A' {|Agent B', Nonce M|} : set evs; \ |
575 \ Notes A' {|Agent B', Nonce PMS|} : set evs; \ |
527 \ Nonce M ~: analz (sees Spy evs); \ |
576 \ Nonce PMS ~: analz (sees Spy evs); \ |
528 \ evs : tls |] \ |
577 \ evs : tls |] \ |
529 \ ==> A=A' & B=B'"; |
578 \ ==> A=A' & B=B'"; |
530 by (prove_unique_tac lemma 1); |
579 by (prove_unique_tac lemma 1); |
531 qed "Notes_unique_M"; |
580 qed "Notes_unique_PMS"; |
532 |
581 |
533 |
582 |
534 |
583 |
535 (*** Protocol goals: if A receives SERVER FINISHED, then B is present |
584 (*** Protocol goals: if A receives SERVER FINISHED, then B is present |
536 and has used the quoted values XA, XB, etc. Note that it is up to A |
585 and has used the quoted values XA, XB, etc. Note that it is up to A |
537 to compare XA with what she originally sent. |
586 to compare XA with what she originally sent. |
538 ***) |
587 ***) |
539 |
588 |
540 (*The mention of her name (A) in X assumes A that B knows who she is.*) |
589 (*The mention of her name (A) in X assumes A that B knows who she is.*) |
541 goal thy |
590 goal thy |
542 "!!evs. [| X = Crypt (serverK(NA,NB,M)) \ |
591 "!!evs. [| X = Crypt (serverK(Na,Nb,M)) \ |
543 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
592 \ (Hash{|Nonce M, Nonce NA, Number XA, Agent A, \ |
544 \ Nonce NA, Agent XA, Agent A, \ |
593 \ Nonce NB, Number XB, Agent B|}); \ |
545 \ Nonce NB, Agent XB, certificate B (pubK B)|}); \ |
594 \ M = PRF(PMS,NA,NB); \ |
546 \ evs : tls; A ~: lost; B ~: lost |] \ |
595 \ evs : tls; A ~: lost; B ~: lost |] \ |
547 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
596 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \ |
548 \ X : parts (sees Spy evs) --> Says B A X : set evs"; |
597 \ X : parts (sees Spy evs) --> Says B A X : set evs"; |
549 by (hyp_subst_tac 1); |
598 by (hyp_subst_tac 1); |
550 by (analz_induct_tac 1); |
599 by (analz_induct_tac 1); |
551 by (REPEAT_FIRST (rtac impI)); |
|
552 (*Fake: the Spy doesn't have the critical session key!*) |
600 (*Fake: the Spy doesn't have the critical session key!*) |
553 by (REPEAT (rtac impI 1)); |
601 by (REPEAT (rtac impI 1)); |
554 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees Spy evsa)" 1); |
602 by (subgoal_tac |
555 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
603 "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1); |
|
604 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, |
556 not_parts_not_analz]) 2); |
605 not_parts_not_analz]) 2); |
557 by (Fake_parts_insert_tac 1); |
606 by (Fake_parts_insert_tac 1); |
558 qed_spec_mp "TrustServerFinished"; |
607 qed_spec_mp "TrustServerFinished"; |
559 |
608 |
560 |
609 |
561 (*This version refers not to SERVER FINISHED but to any message from B. |
610 (*This version refers not to SERVER FINISHED but to any message from B. |
562 We don't assume B has received CERTIFICATE VERIFY, and an intruder could |
611 We don't assume B has received CERTIFICATE VERIFY, and an intruder could |
563 have changed A's identity in all other messages, so we can't be sure |
612 have changed A's identity in all other messages, so we can't be sure |
564 that B sends his message to A. If CLIENT KEY EXCHANGE were augmented |
613 that B sends his message to A. If CLIENT KEY EXCHANGE were augmented |
565 to bind A's identify with M, then we could replace A' by A below.*) |
614 to bind A's identity with M, then we could replace A' by A below.*) |
566 goal thy |
615 goal thy |
567 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
616 "!!evs. [| evs : tls; A ~: lost; B ~: lost; \ |
568 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
617 \ M = PRF(PMS,NA,NB) |] \ |
569 \ Crypt (serverK(NA,NB,M)) Y : parts (sees Spy evs) --> \ |
618 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \ |
570 \ (EX A'. Says B A' (Crypt (serverK(NA,NB,M)) Y) : set evs)"; |
619 \ Crypt (serverK(Na,Nb,M)) Y : parts (sees Spy evs) --> \ |
|
620 \ (EX A'. Says B A' (Crypt (serverK(Na,Nb,M)) Y) : set evs)"; |
|
621 by (hyp_subst_tac 1); |
571 by (analz_induct_tac 1); |
622 by (analz_induct_tac 1); |
572 by (REPEAT_FIRST (rtac impI)); |
623 by (REPEAT_FIRST (rtac impI)); |
573 (*Fake: the Spy doesn't have the critical session key!*) |
624 (*Fake: the Spy doesn't have the critical session key!*) |
574 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees Spy evsa)" 1); |
625 by (subgoal_tac |
575 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
626 "Key (serverK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1); |
|
627 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, |
576 not_parts_not_analz]) 2); |
628 not_parts_not_analz]) 2); |
577 by (Fake_parts_insert_tac 1); |
629 by (Fake_parts_insert_tac 1); |
578 (*ServerFinished. If the message is old then apply induction hypothesis...*) |
630 (*ServerFinished. If the message is old then apply induction hypothesis...*) |
579 by (rtac conjI 1 THEN Blast_tac 2); |
631 by (rtac conjI 1 THEN Blast_tac 2); |
580 (*...otherwise delete induction hyp and use unicity of M.*) |
632 (*...otherwise delete induction hyp and use unicity of PMS.*) |
581 by (thin_tac "?PP-->?QQ" 1); |
633 by (thin_tac "?PP-->?QQ" 1); |
582 by (Step_tac 1); |
634 by (Step_tac 1); |
583 by (subgoal_tac "Nonce M ~: analz (sees Spy evsa)" 1); |
635 by (subgoal_tac "Nonce PMS ~: analz (sees Spy evsSF)" 1); |
584 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2); |
636 by (asm_simp_tac (!simpset addsimps [Spy_not_see_PMS]) 2); |
585 by (blast_tac (!claset addSEs [MPair_parts] |
637 by (blast_tac (!claset addSEs [MPair_parts] |
586 addDs [Notes_Crypt_parts_sees, |
638 addDs [Notes_Crypt_parts_sees, |
587 Says_imp_sees_Spy RS parts.Inj, |
639 Says_imp_sees_Spy RS parts.Inj, |
588 unique_M]) 1); |
640 unique_PMS]) 1); |
589 qed_spec_mp "TrustServerMsg"; |
641 qed_spec_mp "TrustServerMsg"; |
590 |
642 |
591 |
643 |
592 (*** Protocol goal: if B receives any message encrypted with clientK |
644 (*** Protocol goal: if B receives any message encrypted with clientK |
593 then A has sent it, ASSUMING that A chose M. Authentication is |
645 then A has sent it, ASSUMING that A chose PMS. Authentication is |
594 assumed here; B cannot verify it. But if the message is |
646 assumed here; B cannot verify it. But if the message is |
595 CLIENT FINISHED, then B can then check the quoted values XA, XB, etc. |
647 CLIENT FINISHED, then B can then check the quoted values XA, XB, etc. |
596 ***) |
648 ***) |
597 goal thy |
649 goal thy |
598 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
650 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
599 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
651 \ ==> Notes A {|Agent B, Nonce PMS|} : set evs --> \ |
600 \ Crypt (clientK(NA,NB,M)) Y : parts (sees Spy evs) --> \ |
652 \ Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y : parts (sees Spy evs) --> \ |
601 \ Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs"; |
653 \ Says A B (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs"; |
602 by (analz_induct_tac 1); |
654 by (analz_induct_tac 1); |
603 by (REPEAT_FIRST (rtac impI)); |
655 by (REPEAT_FIRST (rtac impI)); |
604 (*Fake: the Spy doesn't have the critical session key!*) |
656 (*Fake: the Spy doesn't have the critical session key!*) |
605 by (subgoal_tac "Key (clientK(NA,NB,M)) ~: analz (sees Spy evsa)" 1); |
657 by (subgoal_tac |
606 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
658 "Key (clientK(Na,Nb,PRF(PMS,NA,NB))) ~: analz (sees Spy evsa)" 1); |
|
659 by (asm_simp_tac (!simpset addsimps [Spy_not_see_MS, |
607 not_parts_not_analz]) 2); |
660 not_parts_not_analz]) 2); |
608 by (Fake_parts_insert_tac 1); |
661 by (Fake_parts_insert_tac 1); |
609 (*ClientFinished. If the message is old then apply induction hypothesis...*) |
662 (*ClientFinished. If the message is old then apply induction hypothesis...*) |
610 by (step_tac (!claset delrules [conjI]) 1); |
663 by (step_tac (!claset delrules [conjI]) 1); |
611 by (subgoal_tac "Nonce M ~: analz (sees Spy evsa)" 1); |
664 by (subgoal_tac "Nonce PMS ~: analz (sees Spy evsCF)" 1); |
612 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2); |
665 by (asm_simp_tac (!simpset addsimps [Spy_not_see_PMS]) 2); |
613 by (blast_tac (!claset addSEs [MPair_parts] |
666 by (blast_tac (!claset addSEs [MPair_parts] |
614 addDs [Notes_unique_M]) 1); |
667 addDs [Notes_unique_PMS]) 1); |
615 qed_spec_mp "TrustClientMsg"; |
668 qed_spec_mp "TrustClientMsg"; |
616 |
669 |
617 |
670 |
618 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to |
671 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to |
619 check a CERTIFICATE VERIFY from A, then A has used the quoted |
672 check a CERTIFICATE VERIFY from A, then A has used the quoted |
620 values XA, XB, etc. Even this one requires A to be uncompromised. |
673 values XA, XB, etc. Even this one requires A to be uncompromised. |
621 ***) |
674 ***) |
622 goal thy |
675 goal thy |
623 "!!evs. [| Says A' B (Crypt (clientK(NA,NB,M)) Y) : set evs; \ |
676 "!!evs. [| Says A' B (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs; \ |
624 \ Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
677 \ Says B A {|Nonce NA, Nonce NB, Number XB, certificate B KB|} \ |
625 \ : set evs; \ |
678 \ : set evs; \ |
626 \ Says A'' B (Crypt (priK A) \ |
679 \ Says A'' B (Crypt (priK A) \ |
627 \ (Hash{|Nonce NB, certificate B KB, Nonce M|})) \ |
680 \ (Hash{|Nonce NB, certificate B KB, Nonce PMS|})) \ |
628 \ : set evs; \ |
681 \ : set evs; \ |
629 \ evs : tls; A ~: lost; B ~: lost |] \ |
682 \ evs : tls; A ~: lost; B ~: lost |] \ |
630 \ ==> Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs"; |
683 \ ==> Says A B (Crypt (clientK(Na,Nb,PRF(PMS,NA,NB))) Y) : set evs"; |
631 by (blast_tac (!claset addSIs [TrustClientMsg, UseCertVerify] |
684 by (blast_tac (!claset addSIs [TrustClientMsg, UseCertVerify] |
632 addDs [Says_imp_sees_Spy RS parts.Inj]) 1); |
685 addDs [Says_imp_sees_Spy RS parts.Inj]) 1); |
633 qed "AuthClientFinished"; |
686 qed "AuthClientFinished"; |