173 |
165 |
174 bind_thm ("Spy_analz_priK_D", analz_subset_parts RS subsetD RS Spy_see_priK_D); |
166 bind_thm ("Spy_analz_priK_D", analz_subset_parts RS subsetD RS Spy_see_priK_D); |
175 AddSDs [Spy_see_priK_D, Spy_analz_priK_D]; |
167 AddSDs [Spy_see_priK_D, Spy_analz_priK_D]; |
176 |
168 |
177 |
169 |
|
170 (*This lemma says that no false certificates exist. One might extend the |
|
171 model to include bogus certificates for the lost agents, but there seems |
|
172 little point in doing so: the loss of their private keys is a worse |
|
173 breach of security.*) |
|
174 goalw thy [certificate_def] |
|
175 "!!evs. evs : tls \ |
|
176 \ ==> certificate B KB : parts (sees lost Spy evs) --> KB = pubK B"; |
|
177 by (etac tls.induct 1); |
|
178 by (ALLGOALS (asm_full_simp_tac (!simpset setloop split_tac [expand_if]))); |
|
179 by (Fake_parts_insert_tac 2); |
|
180 by (Blast_tac 1); |
|
181 bind_thm ("Server_cert_pubB", result() RSN (2, rev_mp)); |
|
182 |
|
183 |
|
184 (*Replace key KB in ClientCertKeyEx by (pubK B) *) |
|
185 val ClientCertKeyEx_tac = |
|
186 forward_tac [Says_imp_sees_Spy' RS parts.Inj RS |
|
187 parts.Snd RS parts.Snd RS parts.Snd RS Server_cert_pubB] |
|
188 THEN' assume_tac |
|
189 THEN' hyp_subst_tac; |
|
190 |
|
191 fun analz_induct_tac i = |
|
192 etac tls.induct i THEN |
|
193 ClientCertKeyEx_tac (i+7) THEN (*ClientFinished*) |
|
194 ClientCertKeyEx_tac (i+6) THEN (*CertVerify*) |
|
195 ClientCertKeyEx_tac (i+5) THEN (*ClientCertKeyEx*) |
|
196 rewrite_goals_tac [certificate_def] THEN |
|
197 ALLGOALS (asm_simp_tac |
|
198 (!simpset addsimps [not_parts_not_analz] |
|
199 setloop split_tac [expand_if])) THEN |
|
200 (*Remove instances of pubK B: the Spy already knows all public keys. |
|
201 Combining the two simplifier calls makes them run extremely slowly.*) |
|
202 ALLGOALS (asm_simp_tac |
|
203 (!simpset addsimps [insert_absorb] |
|
204 setloop split_tac [expand_if])); |
|
205 |
|
206 |
|
207 (*** Hashing of nonces ***) |
|
208 |
178 (*Every Nonce that's hashed is already in past traffic. *) |
209 (*Every Nonce that's hashed is already in past traffic. *) |
179 goal thy "!!evs. [| Hash {|Nonce N, X|} : parts (sees lost Spy evs); \ |
210 goal thy "!!evs. [| Hash {|Nonce N, X|} : parts (sees lost Spy evs); \ |
180 \ evs : tls |] \ |
211 \ evs : tls |] \ |
181 \ ==> Nonce N : parts (sees lost Spy evs)"; |
212 \ ==> Nonce N : parts (sees lost Spy evs)"; |
182 by (etac rev_mp 1); |
213 by (etac rev_mp 1); |
183 by (etac tls.induct 1); |
214 by (etac tls.induct 1); |
184 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
215 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees] |
185 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj] |
216 setloop split_tac [expand_if]))); |
186 addSEs partsEs) 1); |
217 by (Fake_parts_insert_tac 2); |
187 by (Fake_parts_insert_tac 1); |
218 by (REPEAT (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj] |
|
219 addSEs partsEs) 1)); |
188 qed "Hash_imp_Nonce1"; |
220 qed "Hash_imp_Nonce1"; |
189 |
221 |
190 (*Lemma needed to prove Hash_Hash_imp_Nonce*) |
222 (*Lemma needed to prove Hash_Hash_imp_Nonce*) |
191 goal thy "!!evs. [| Hash{|Nonce NA, Nonce NB, Nonce M|} \ |
223 goal thy "!!evs. [| Hash{|Nonce NA, Nonce NB, Nonce M|} \ |
192 \ : parts (sees lost Spy evs); \ |
224 \ : parts (sees lost Spy evs); \ |
193 \ evs : tls |] \ |
225 \ evs : tls |] \ |
194 \ ==> Nonce M : parts (sees lost Spy evs)"; |
226 \ ==> Nonce M : parts (sees lost Spy evs)"; |
195 by (etac rev_mp 1); |
227 by (etac rev_mp 1); |
196 by (etac tls.induct 1); |
228 by (etac tls.induct 1); |
197 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
229 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees] |
198 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj] |
230 setloop split_tac [expand_if]))); |
199 addSEs partsEs) 1); |
231 by (Fake_parts_insert_tac 2); |
200 by (Fake_parts_insert_tac 1); |
232 by (blast_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj] |
|
233 addSEs partsEs) 1); |
201 qed "Hash_imp_Nonce2"; |
234 qed "Hash_imp_Nonce2"; |
202 AddSDs [Hash_imp_Nonce2]; |
235 AddSDs [Hash_imp_Nonce2]; |
203 |
236 |
|
237 |
|
238 goal thy "!!evs. [| Notes A {|Agent B, X|} : set evs; evs : tls |] \ |
|
239 \ ==> Crypt (pubK B) X : parts (sees lost Spy evs)"; |
|
240 by (etac rev_mp 1); |
|
241 by (analz_induct_tac 1); |
|
242 by (blast_tac (!claset addIs [parts_insertI]) 1); |
|
243 qed "Notes_Crypt_parts_sees"; |
|
244 |
|
245 |
|
246 (*NEEDED??*) |
204 goal thy "!!evs. [| Hash {| Hash{|Nonce NA, Nonce NB, Nonce M|}, X |} \ |
247 goal thy "!!evs. [| Hash {| Hash{|Nonce NA, Nonce NB, Nonce M|}, X |} \ |
205 \ : parts (sees lost Spy evs); \ |
248 \ : parts (sees lost Spy evs); \ |
206 \ evs : tls |] \ |
249 \ evs : tls |] \ |
207 \ ==> Nonce M : parts (sees lost Spy evs)"; |
250 \ ==> Nonce M : parts (sees lost Spy evs)"; |
208 by (etac rev_mp 1); |
251 by (etac rev_mp 1); |
209 by (etac tls.induct 1); |
252 by (etac tls.induct 1); |
210 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees]))); |
253 by (ALLGOALS (asm_simp_tac (!simpset addsimps [parts_insert_sees] |
211 by (step_tac (!claset addSDs [Says_imp_sees_Spy' RS parts.Inj] |
254 setloop split_tac [expand_if]))); |
|
255 by (Fake_parts_insert_tac 2); |
|
256 by (step_tac (!claset addSDs [Notes_Crypt_parts_sees, |
|
257 Says_imp_sees_Spy' RS parts.Inj] |
212 addSEs partsEs) 1); |
258 addSEs partsEs) 1); |
213 by (Fake_parts_insert_tac 1); |
|
214 qed "Hash_Hash_imp_Nonce"; |
259 qed "Hash_Hash_imp_Nonce"; |
215 |
260 |
216 |
261 |
217 (*NEEDED?? |
262 (*NEEDED?? |
218 Every Nonce that's hashed is already in past traffic. |
263 Every Nonce that's hashed is already in past traffic. |
246 \ ==> Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
292 \ ==> Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
247 \ : set evs --> \ |
293 \ : set evs --> \ |
248 \ X : parts (sees lost Spy evs) --> Says A B X : set evs"; |
294 \ X : parts (sees lost Spy evs) --> Says A B X : set evs"; |
249 by (hyp_subst_tac 1); |
295 by (hyp_subst_tac 1); |
250 by (etac tls.induct 1); |
296 by (etac tls.induct 1); |
251 by (ALLGOALS Asm_simp_tac); |
297 by (ALLGOALS (asm_simp_tac (!simpset setloop split_tac [expand_if]))); |
252 by (Fake_parts_insert_tac 1); |
298 by (Fake_parts_insert_tac 1); |
253 (*ServerHello: nonce NB cannot be in X because it's fresh!*) |
299 (*ServerHello: nonce NB cannot be in X because it's fresh!*) |
254 by (blast_tac (!claset addSDs [Hash_imp_Nonce1] |
300 by (blast_tac (!claset addSDs [Hash_imp_Nonce1] |
255 addSEs sees_Spy_partsEs) 1); |
301 addSEs sees_Spy_partsEs) 1); |
256 qed_spec_mp "TrustCertVerify"; |
302 qed_spec_mp "TrustCertVerify"; |
257 |
303 |
258 |
304 |
|
305 (*If CERTIFICATE VERIFY is present then A has chosen M.*) |
259 goal thy |
306 goal thy |
260 "!!evs. [| evs : tls; A ~= Spy |] \ |
307 "!!evs. [| Crypt (priK A) (Hash{|Nonce NB, certificate B KB, Nonce M|}) \ |
261 \ ==> Says A B (Crypt (priK A) \ |
308 \ : parts (sees lost Spy evs); \ |
262 \ (Hash{|Nonce NB, certificate B KB, Nonce M|})) : set evs \ |
309 \ evs : tls; A ~: lost |] \ |
263 \ --> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} : set evs"; |
310 \ ==> Notes A {|Agent B, Nonce M|} : set evs"; |
264 by (etac tls.induct 1); |
311 be rev_mp 1; |
265 by (ALLGOALS Asm_full_simp_tac); |
312 by (etac tls.induct 1); |
266 bind_thm ("UseCertVerify", result() RSN (2, rev_mp)); |
313 by (ALLGOALS (asm_full_simp_tac (!simpset setloop split_tac [expand_if]))); |
267 |
|
268 |
|
269 (*This lemma says that no false certificates exist. One might extend the |
|
270 model to include bogus certificates for the lost agents, but there seems |
|
271 little point in doing so: the loss of their private keys is a worse |
|
272 breach of security.*) |
|
273 goalw thy [certificate_def] |
|
274 "!!evs. evs : tls \ |
|
275 \ ==> certificate B KB : parts (sees lost Spy evs) --> KB = pubK B"; |
|
276 by (etac tls.induct 1); |
|
277 by (ALLGOALS Asm_simp_tac); |
|
278 by (Fake_parts_insert_tac 2); |
314 by (Fake_parts_insert_tac 2); |
279 by (Blast_tac 1); |
315 by (Blast_tac 1); |
280 bind_thm ("Server_cert_pubB", result() RSN (2, rev_mp)); |
316 qed "UseCertVerify"; |
281 |
317 |
282 |
|
283 (*Replace key KB in ClientCertKeyEx by (pubK B) *) |
|
284 val ClientCertKeyEx_tac = |
|
285 forward_tac [Says_imp_sees_Spy' RS parts.Inj RS |
|
286 parts.Snd RS parts.Snd RS parts.Snd RS Server_cert_pubB] |
|
287 THEN' assume_tac |
|
288 THEN' hyp_subst_tac; |
|
289 |
|
290 fun analz_induct_tac i = |
|
291 etac tls.induct i THEN |
|
292 ClientCertKeyEx_tac (i+5) THEN |
|
293 ALLGOALS (asm_simp_tac |
|
294 (!simpset addsimps [not_parts_not_analz] |
|
295 setloop split_tac [expand_if])) THEN |
|
296 (*Remove instances of pubK B: the Spy already knows all public keys. |
|
297 Combining the two simplifier calls makes them run extremely slowly.*) |
|
298 ALLGOALS (asm_simp_tac |
|
299 (!simpset addsimps [insert_absorb] |
|
300 setloop split_tac [expand_if])); |
|
301 |
|
302 (*** Specialized rewriting for the analz_image_... theorems ***) |
|
303 |
|
304 goal thy "insert (Key K) H = Key `` {K} Un H"; |
|
305 by (Blast_tac 1); |
|
306 qed "insert_Key_singleton"; |
|
307 |
|
308 goal thy "insert (Key K) (Key``KK Un C) = Key `` (insert K KK) Un C"; |
|
309 by (Blast_tac 1); |
|
310 qed "insert_Key_image"; |
|
311 |
|
312 (*Reverse the normal simplification of "image" to build up (not break down) |
|
313 the set of keys. Based on analz_image_freshK_ss, but simpler.*) |
|
314 val analz_image_keys_ss = |
|
315 !simpset delsimps [image_insert, image_Un] |
|
316 addsimps [image_insert RS sym, image_Un RS sym, |
|
317 rangeI, |
|
318 insert_Key_singleton, |
|
319 insert_Key_image, Un_assoc RS sym] |
|
320 setloop split_tac [expand_if]; |
|
321 |
318 |
322 (*No collection of keys can help the spy get new private keys*) |
319 (*No collection of keys can help the spy get new private keys*) |
323 goal thy |
320 goal thy |
324 "!!evs. evs : tls ==> \ |
321 "!!evs. evs : tls ==> \ |
325 \ ALL KK. (Key(priK B) : analz (Key``KK Un (sees lost Spy evs))) = \ |
322 \ ALL KK. (Key(priK B) : analz (Key``KK Un (sees lost Spy evs))) = \ |
326 \ (priK B : KK | B : lost)"; |
323 \ (priK B : KK | B : lost)"; |
327 by (etac tls.induct 1); |
324 by (etac tls.induct 1); |
328 by (ALLGOALS (asm_simp_tac analz_image_keys_ss)); |
325 by (ALLGOALS |
|
326 (asm_simp_tac (analz_image_keys_ss |
|
327 addsimps (certificate_def::keys_distinct)))); |
329 (*Fake*) |
328 (*Fake*) |
330 by (spy_analz_tac 2); |
329 by (spy_analz_tac 2); |
331 (*Base*) |
330 (*Base*) |
332 by (Blast_tac 1); |
331 by (Blast_tac 1); |
333 qed_spec_mp "analz_image_priK"; |
332 qed_spec_mp "analz_image_priK"; |
347 \ (Nonce N : analz (Key``KK Un (sees lost Spy evs))) = \ |
346 \ (Nonce N : analz (Key``KK Un (sees lost Spy evs))) = \ |
348 \ (Nonce N : analz (sees lost Spy evs))"; |
347 \ (Nonce N : analz (sees lost Spy evs))"; |
349 by (etac tls.induct 1); |
348 by (etac tls.induct 1); |
350 by (ClientCertKeyEx_tac 6); |
349 by (ClientCertKeyEx_tac 6); |
351 by (REPEAT_FIRST (resolve_tac [allI, impI])); |
350 by (REPEAT_FIRST (resolve_tac [allI, impI])); |
352 by (REPEAT_FIRST (rtac lemma )); |
351 by (REPEAT_FIRST (rtac lemma)); |
353 (*SLOW: 30s!*) |
352 writeln"SLOW simplification: 50 secs!??"; |
354 by (ALLGOALS (asm_simp_tac analz_image_keys_ss)); |
353 by (ALLGOALS |
355 by (ALLGOALS (asm_simp_tac |
354 (asm_simp_tac (analz_image_keys_ss |
356 (!simpset addsimps [analz_image_priK, insert_absorb]))); |
355 addsimps (analz_image_priK::certificate_def:: |
|
356 keys_distinct)))); |
|
357 by (ALLGOALS (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_priK]))); |
|
358 by (ALLGOALS (asm_simp_tac (!simpset addsimps [insert_absorb]))); |
357 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*) |
359 (*ClientCertKeyEx: a nonce is sent, but one needs a priK to read it.*) |
358 by (Blast_tac 3); |
360 by (Blast_tac 3); |
359 (*Fake*) |
361 (*Fake*) |
360 by (spy_analz_tac 2); |
362 by (spy_analz_tac 2); |
361 (*Base*) |
363 (*Base*) |
362 by (Blast_tac 1); |
364 by (Blast_tac 1); |
363 qed_spec_mp "analz_image_keys"; |
365 qed_spec_mp "analz_image_keys"; |
364 |
366 |
365 |
367 |
366 (*If A sends ClientCertKeyEx to an uncompromised B, then M will stay secret. |
368 (*If A sends ClientCertKeyEx to an uncompromised B, then M will stay secret.*) |
367 The assumption is A~=Spy, not A~:lost, since A doesn't use her private key |
369 goal thy |
368 here.*) |
370 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
369 goalw thy [certificate_def] |
371 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
370 "!!evs. [| evs : tls; A~=Spy; B ~: lost |] \ |
372 \ Nonce M ~: analz (sees lost Spy evs)"; |
371 \ ==> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} \ |
|
372 \ : set evs --> Nonce M ~: analz (sees lost Spy evs)"; |
|
373 by (analz_induct_tac 1); |
373 by (analz_induct_tac 1); |
374 (*ClientHello*) |
374 (*ClientHello*) |
375 by (blast_tac (!claset addSEs sees_Spy_partsEs) 3); |
375 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
|
376 addSEs sees_Spy_partsEs) 3); |
376 (*SpyKeys*) |
377 (*SpyKeys*) |
377 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2); |
378 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 2); |
378 (*Fake*) |
379 (*Fake*) |
379 by (spy_analz_tac 1); |
380 by (spy_analz_tac 1); |
380 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*) |
381 (*ServerHello and ClientCertKeyEx: mostly freshness reasoning*) |
381 by (REPEAT (blast_tac (!claset addSEs partsEs |
382 by (REPEAT (blast_tac (!claset addSEs partsEs |
382 addDs [impOfSubs analz_subset_parts, |
383 addDs [Notes_Crypt_parts_sees, |
|
384 impOfSubs analz_subset_parts, |
383 Says_imp_sees_Spy' RS analz.Inj]) 1)); |
385 Says_imp_sees_Spy' RS analz.Inj]) 1)); |
384 bind_thm ("Spy_not_see_premaster_secret", result() RSN (2, rev_mp)); |
386 bind_thm ("Spy_not_see_premaster_secret", result() RSN (2, rev_mp)); |
385 |
387 |
386 |
388 |
387 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***) |
389 (*** Protocol goal: serverK(NA,NB,M) and clientK(NA,NB,M) remain secure ***) |
388 |
390 |
389 (*The two proofs are identical*) |
391 (** First, some lemmas about those write keys. The proofs for serverK are |
390 goal thy |
392 nearly identical to those for clientK. **) |
391 "!!evs. [| Nonce M ~: analz (sees lost Spy evs); \ |
393 |
392 \ evs : tls |] \ |
394 (*Lemma: those write keys are never sent if M is secure. |
|
395 Converse doesn't hold; betraying M doesn't force the keys to be sent!*) |
|
396 |
|
397 goal thy |
|
398 "!!evs. [| Nonce M ~: analz (sees lost Spy evs); evs : tls |] \ |
393 \ ==> Key (clientK(NA,NB,M)) ~: parts (sees lost Spy evs)"; |
399 \ ==> Key (clientK(NA,NB,M)) ~: parts (sees lost Spy evs)"; |
394 by (etac rev_mp 1); |
400 by (etac rev_mp 1); |
395 by (analz_induct_tac 1); |
401 by (analz_induct_tac 1); |
396 (*SpyKeys*) |
402 (*SpyKeys*) |
397 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3); |
403 by (asm_simp_tac (analz_image_keys_ss addsimps [analz_image_keys]) 3); |
415 by (spy_analz_tac 2); |
423 by (spy_analz_tac 2); |
416 (*Base*) |
424 (*Base*) |
417 by (Blast_tac 1); |
425 by (Blast_tac 1); |
418 qed "serverK_notin_parts"; |
426 qed "serverK_notin_parts"; |
419 |
427 |
|
428 Addsimps [serverK_notin_parts]; |
|
429 AddSEs [serverK_notin_parts RSN (2, rev_notE)]; |
|
430 |
|
431 (*Lemma: those write keys are never used if M is fresh. |
|
432 Converse doesn't hold; betraying M doesn't force the keys to be sent! |
|
433 NOT suitable as safe elim rules.*) |
|
434 |
|
435 goal thy |
|
436 "!!evs. [| Nonce M ~: used evs; evs : tls |] \ |
|
437 \ ==> Crypt (clientK(NA,NB,M)) Y ~: parts (sees lost Spy evs)"; |
|
438 by (etac rev_mp 1); |
|
439 by (analz_induct_tac 1); |
|
440 (*ClientFinished: since M is fresh, a different instance of clientK was used.*) |
|
441 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
|
442 addSEs sees_Spy_partsEs) 3); |
|
443 by (Fake_parts_insert_tac 2); |
|
444 (*Base*) |
|
445 by (Blast_tac 1); |
|
446 qed "Crypt_clientK_notin_parts"; |
|
447 |
|
448 Addsimps [Crypt_clientK_notin_parts]; |
|
449 AddEs [Crypt_clientK_notin_parts RSN (2, rev_notE)]; |
|
450 |
|
451 goal thy |
|
452 "!!evs. [| Nonce M ~: used evs; evs : tls |] \ |
|
453 \ ==> Crypt (serverK(NA,NB,M)) Y ~: parts (sees lost Spy evs)"; |
|
454 by (etac rev_mp 1); |
|
455 by (analz_induct_tac 1); |
|
456 (*ServerFinished: since M is fresh, a different instance of serverK was used.*) |
|
457 by (blast_tac (!claset addSDs [Notes_Crypt_parts_sees] |
|
458 addSEs sees_Spy_partsEs) 3); |
|
459 by (Fake_parts_insert_tac 2); |
|
460 (*Base*) |
|
461 by (Blast_tac 1); |
|
462 qed "Crypt_serverK_notin_parts"; |
|
463 |
|
464 Addsimps [Crypt_serverK_notin_parts]; |
|
465 AddEs [Crypt_serverK_notin_parts RSN (2, rev_notE)]; |
|
466 |
|
467 |
|
468 (*Weakening A~:lost to A~=Spy would complicate later uses of the rule*) |
|
469 goal thy |
|
470 "!!evs. [| Says A B {|certA, Crypt KB (Nonce M)|} : set evs; \ |
|
471 \ A ~: lost; evs : tls |] ==> KB = pubK B"; |
|
472 be rev_mp 1; |
|
473 by (analz_induct_tac 1); |
|
474 qed "A_Crypt_pubB"; |
|
475 |
|
476 |
|
477 (*** Unicity results for M, the pre-master-secret ***) |
|
478 |
|
479 (*Induction for theorems of the form X ~: analz (sees lost Spy evs) --> ... |
|
480 It simplifies the proof by discarding needless information about |
|
481 analz (insert X (sees lost Spy evs)) |
|
482 *) |
|
483 fun analz_mono_parts_induct_tac i = |
|
484 etac tls.induct i THEN |
|
485 ClientCertKeyEx_tac (i+5) THEN (*ClientCertKeyEx*) |
|
486 REPEAT_FIRST analz_mono_contra_tac; |
|
487 |
|
488 |
|
489 (*M determines B. Proof borrowed from NS_Public/unique_NA and from Yahalom*) |
|
490 goal thy |
|
491 "!!evs. [| Nonce M ~: analz (sees lost Spy evs); evs : tls |] \ |
|
492 \ ==> EX B'. ALL B. \ |
|
493 \ Crypt (pubK B) (Nonce M) : parts (sees lost Spy evs) --> B=B'"; |
|
494 by (etac rev_mp 1); |
|
495 by (analz_mono_parts_induct_tac 1); |
|
496 by (prove_simple_subgoals_tac 1); |
|
497 by (asm_simp_tac (!simpset addsimps [all_conj_distrib] |
|
498 setloop split_tac [expand_if]) 2); |
|
499 (*ClientCertKeyEx*) |
|
500 by (expand_case_tac "M = ?y" 2 THEN |
|
501 REPEAT (blast_tac (!claset addSEs partsEs) 2)); |
|
502 by (Fake_parts_insert_tac 1); |
|
503 val lemma = result(); |
|
504 |
|
505 goal thy |
|
506 "!!evs. [| Crypt(pubK B) (Nonce M) : parts (sees lost Spy evs); \ |
|
507 \ Crypt(pubK B') (Nonce M) : parts (sees lost Spy evs); \ |
|
508 \ Nonce M ~: analz (sees lost Spy evs); \ |
|
509 \ evs : tls |] \ |
|
510 \ ==> B=B'"; |
|
511 by (prove_unique_tac lemma 1); |
|
512 qed "unique_M"; |
|
513 |
|
514 |
|
515 (*In A's note to herself, M determines A and B.*) |
|
516 goal thy |
|
517 "!!evs. [| Nonce M ~: analz (sees lost Spy evs); evs : tls |] \ |
|
518 \ ==> EX A' B'. ALL A B. \ |
|
519 \ Notes A {|Agent B, Nonce M|} : set evs --> A=A' & B=B'"; |
|
520 by (etac rev_mp 1); |
|
521 by (analz_mono_parts_induct_tac 1); |
|
522 by (prove_simple_subgoals_tac 1); |
|
523 by (asm_simp_tac (!simpset addsimps [all_conj_distrib]) 1); |
|
524 (*ClientCertKeyEx: if M is fresh, then it can't appear in Notes A X.*) |
|
525 by (expand_case_tac "M = ?y" 1 THEN |
|
526 blast_tac (!claset addSDs [Notes_Crypt_parts_sees] addSEs partsEs) 1); |
|
527 val lemma = result(); |
|
528 |
|
529 goal thy |
|
530 "!!evs. [| Notes A {|Agent B, Nonce M|} : set evs; \ |
|
531 \ Notes A' {|Agent B', Nonce M|} : set evs; \ |
|
532 \ Nonce M ~: analz (sees lost Spy evs); \ |
|
533 \ evs : tls |] \ |
|
534 \ ==> A=A' & B=B'"; |
|
535 by (prove_unique_tac lemma 1); |
|
536 qed "Notes_unique_M"; |
|
537 |
|
538 |
420 |
539 |
421 (*** Protocol goals: if A receives SERVER FINISHED, then B is present |
540 (*** Protocol goals: if A receives SERVER FINISHED, then B is present |
422 and has used the quoted values XA, XB, etc. Note that it is up to A |
541 and has used the quoted values XA, XB, etc. Note that it is up to A |
423 to compare XA with what she originally sent. |
542 to compare XA with what she originally sent. |
424 ***) |
543 ***) |
425 |
544 |
426 goalw thy [certificate_def] |
545 (*The mention of her name (A) in X assumes A that B knows who she is.*) |
427 "!!evs. [| X = Crypt (serverK(NA,NB,M)) \ |
546 goal thy |
428 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
547 "!!evs. [| X = Crypt (serverK(NA,NB,M)) \ |
429 \ Nonce NA, Agent XA, Agent A, \ |
548 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
|
549 \ Nonce NA, Agent XA, Agent A, \ |
430 \ Nonce NB, Agent XB, certificate B (pubK B)|}); \ |
550 \ Nonce NB, Agent XB, certificate B (pubK B)|}); \ |
431 \ evs : tls; A~=Spy; B ~: lost |] \ |
551 \ evs : tls; A ~: lost; B ~: lost |] \ |
432 \ ==> Says A B {|certificate A (pubK A), Crypt KB (Nonce M)|} \ |
552 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
433 \ : set evs --> \ |
|
434 \ X : parts (sees lost Spy evs) --> Says B A X : set evs"; |
553 \ X : parts (sees lost Spy evs) --> Says B A X : set evs"; |
435 by (hyp_subst_tac 1); |
554 by (hyp_subst_tac 1); |
436 by (etac tls.induct 1); |
555 by (analz_induct_tac 1); |
437 by (ALLGOALS Asm_simp_tac); |
556 by (REPEAT_FIRST (rtac impI)); |
438 (*ClientCertKeyEx: M isn't in the Hash because it's fresh!*) |
|
439 by (blast_tac (!claset addSDs [Hash_Hash_imp_Nonce] |
|
440 addSEs sees_Spy_partsEs) 2); |
|
441 (*Fake: the Spy doesn't have the critical session key!*) |
557 (*Fake: the Spy doesn't have the critical session key!*) |
442 by (REPEAT (rtac impI 1)); |
558 by (REPEAT (rtac impI 1)); |
443 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1); |
559 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1); |
444 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
560 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
445 serverK_notin_parts, |
|
446 not_parts_not_analz]) 2); |
561 not_parts_not_analz]) 2); |
447 by (Fake_parts_insert_tac 1); |
562 by (Fake_parts_insert_tac 1); |
448 qed_spec_mp "TrustServerFinished"; |
563 qed_spec_mp "TrustServerFinished"; |
449 |
564 |
450 |
565 |
451 (*** Protocol goal: if B receives CLIENT FINISHED, then A has used the |
566 (*This version refers not to SERVER FINISHED but to any message from B. |
452 quoted values XA, XB, etc., which B can then check. BUT NOTE: |
567 We don't assume B has received CERTIFICATE VERIFY, and an intruder could |
453 B has no way of knowing that A is the sender of CLIENT CERTIFICATE! |
568 have changed A's identity in all other messages, so we can't be sure |
|
569 that B sends his message to A.*) |
|
570 goal thy |
|
571 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
|
572 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
|
573 \ Crypt (serverK(NA,NB,M)) Y : parts (sees lost Spy evs) --> \ |
|
574 \ (EX A'. Says B A' (Crypt (serverK(NA,NB,M)) Y) : set evs)"; |
|
575 by (analz_induct_tac 1); |
|
576 by (REPEAT_FIRST (rtac impI)); |
|
577 (*Fake: the Spy doesn't have the critical session key!*) |
|
578 by (subgoal_tac "Key (serverK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1); |
|
579 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
|
580 not_parts_not_analz]) 2); |
|
581 by (Fake_parts_insert_tac 1); |
|
582 (*ServerFinished. If the message is old then apply induction hypothesis...*) |
|
583 by (rtac conjI 1 THEN Blast_tac 2); |
|
584 (*...otherwise delete induction hyp and use unicity of M.*) |
|
585 by (thin_tac "?PP-->?QQ" 1); |
|
586 by (Step_tac 1); |
|
587 by (subgoal_tac "Nonce M ~: analz (sees lost Spy evsa)" 1); |
|
588 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2); |
|
589 by (blast_tac (!claset addSEs [MPair_parts] |
|
590 addDs [Notes_Crypt_parts_sees, |
|
591 Says_imp_sees_Spy' RS parts.Inj, |
|
592 unique_M]) 1); |
|
593 qed_spec_mp "TrustServerMsg"; |
|
594 |
|
595 |
|
596 (*** Protocol goal: if B receives any message encrypted with clientK |
|
597 then A has sent it, ASSUMING that A chose M. Authentication is |
|
598 assumed here; B cannot verify it. But if the message is |
|
599 CLIENT FINISHED, then B can then check the quoted values XA, XB, etc. |
454 ***) |
600 ***) |
455 goalw thy [certificate_def] |
601 goal thy |
456 "!!evs. [| X = Crypt (clientK(NA,NB,M)) \ |
602 "!!evs. [| evs : tls; A ~: lost; B ~: lost |] \ |
457 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
603 \ ==> Notes A {|Agent B, Nonce M|} : set evs --> \ |
458 \ Nonce NA, Agent XA, \ |
604 \ Crypt (clientK(NA,NB,M)) Y : parts (sees lost Spy evs) --> \ |
459 \ certificate A (pubK A), \ |
605 \ Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs"; |
460 \ Nonce NB, Agent XB, Agent B|}); \ |
606 by (analz_induct_tac 1); |
461 \ evs : tls; A~=Spy; B ~: lost |] \ |
607 by (REPEAT_FIRST (rtac impI)); |
462 \ ==> Says A B {|certificate A (pubK A), \ |
|
463 \ Crypt KB (Nonce M)|} : set evs --> \ |
|
464 \ X : parts (sees lost Spy evs) --> Says A B X : set evs"; |
|
465 by (hyp_subst_tac 1); |
|
466 by (etac tls.induct 1); |
|
467 by (ALLGOALS Asm_simp_tac); |
|
468 (*ClientCertKeyEx: M isn't in the Hash because it's fresh!*) |
|
469 by (blast_tac (!claset addSDs [Hash_Hash_imp_Nonce] |
|
470 addSEs sees_Spy_partsEs) 2); |
|
471 (*Fake: the Spy doesn't have the critical session key!*) |
608 (*Fake: the Spy doesn't have the critical session key!*) |
472 by (REPEAT (rtac impI 1)); |
|
473 by (subgoal_tac "Key (clientK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1); |
609 by (subgoal_tac "Key (clientK(NA,NB,M)) ~: analz (sees lost Spy evsa)" 1); |
474 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
610 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret, |
475 clientK_notin_parts, |
|
476 not_parts_not_analz]) 2); |
611 not_parts_not_analz]) 2); |
477 by (Fake_parts_insert_tac 1); |
612 by (Fake_parts_insert_tac 1); |
478 qed_spec_mp "TrustClientFinished"; |
613 (*ClientFinished. If the message is old then apply induction hypothesis...*) |
|
614 by (step_tac (!claset delrules [conjI]) 1); |
|
615 by (subgoal_tac "Nonce M ~: analz (sees lost Spy evsa)" 1); |
|
616 by (asm_simp_tac (!simpset addsimps [Spy_not_see_premaster_secret]) 2); |
|
617 by (blast_tac (!claset addSEs [MPair_parts] |
|
618 addDs [Notes_unique_M]) 1); |
|
619 qed_spec_mp "TrustClientMsg"; |
479 |
620 |
480 |
621 |
481 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to |
622 (*** Protocol goal: if B receives CLIENT FINISHED, and if B is able to |
482 check a CERTIFICATE VERIFY from A, then A has used the quoted |
623 check a CERTIFICATE VERIFY from A, then A has used the quoted |
483 values XA, XB, etc. Even this one requires A to be uncompromised. |
624 values XA, XB, etc. Even this one requires A to be uncompromised. |
484 ***) |
625 ***) |
485 goal thy |
626 goal thy |
486 "!!evs. [| X = Crypt (clientK(NA,NB,M)) \ |
627 "!!evs. [| Says A' B (Crypt (clientK(NA,NB,M)) Y) : set evs; \ |
487 \ (Hash{|Hash{|Nonce NA, Nonce NB, Nonce M|}, \ |
628 \ Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
488 \ Nonce NA, Agent XA, \ |
629 \ : set evs; \ |
489 \ certificate A (pubK A), \ |
630 \ Says A'' B (Crypt (priK A) \ |
490 \ Nonce NB, Agent XB, Agent B|}); \ |
631 \ (Hash{|Nonce NB, certificate B KB, Nonce M|})) \ |
491 \ Says A' B X : set evs; \ |
632 \ : set evs; \ |
492 \ Says B A {|Nonce NA, Nonce NB, Agent XB, certificate B KB|} \ |
633 \ evs : tls; A ~: lost; B ~: lost |] \ |
493 \ : set evs; \ |
634 \ ==> Says A B (Crypt (clientK(NA,NB,M)) Y) : set evs"; |
494 \ Says A'' B (Crypt (priK A) \ |
635 by (blast_tac (!claset addSIs [TrustClientMsg, UseCertVerify] |
495 \ (Hash{|Nonce NB, certificate B KB, Nonce M|})) \ |
636 addDs [Says_imp_sees_Spy RS parts.Inj]) 1); |
496 \ : set evs; \ |
637 qed "AuthClientFinished"; |
497 \ evs : tls; A ~: lost; B ~: lost |] \ |
|
498 \ ==> Says A B X : set evs"; |
|
499 br TrustClientFinished 1; |
|
500 br (TrustCertVerify RS UseCertVerify) 5; |
|
501 by (REPEAT_FIRST (ares_tac [refl])); |
|
502 by (ALLGOALS |
|
503 (asm_full_simp_tac (!simpset addsimps [Says_imp_sees_Spy RS parts.Inj]))); |
|
504 qed_spec_mp "AuthClientFinished"; |
|