31 |
31 |
32 AddIffs [SesKeyLife_LB, AutLife_LB]; |
32 AddIffs [SesKeyLife_LB, AutLife_LB]; |
33 |
33 |
34 |
34 |
35 (*A "possibility property": there are traces that reach the end.*) |
35 (*A "possibility property": there are traces that reach the end.*) |
36 goal thy |
36 Goal |
37 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
37 "!!A B. [| A ~= B; A ~= Server; B ~= Server |] \ |
38 \ ==> EX Timestamp K. EX evs: kerberos_ban. \ |
38 \ ==> EX Timestamp K. EX evs: kerberos_ban. \ |
39 \ Says B A (Crypt K (Number Timestamp)) \ |
39 \ Says B A (Crypt K (Number Timestamp)) \ |
40 \ : set evs"; |
40 \ : set evs"; |
41 by (REPEAT (resolve_tac [exI,bexI] 1)); |
41 by (REPEAT (resolve_tac [exI,bexI] 1)); |
50 |
50 |
51 |
51 |
52 (**** Inductive proofs about kerberos_ban ****) |
52 (**** Inductive proofs about kerberos_ban ****) |
53 |
53 |
54 (*Nobody sends themselves messages*) |
54 (*Nobody sends themselves messages*) |
55 goal thy "!!evs. evs : kerberos_ban ==> ALL A X. Says A A X ~: set evs"; |
55 Goal "!!evs. evs : kerberos_ban ==> ALL A X. Says A A X ~: set evs"; |
56 by (etac kerberos_ban.induct 1); |
56 by (etac kerberos_ban.induct 1); |
57 by Auto_tac; |
57 by Auto_tac; |
58 qed_spec_mp "not_Says_to_self"; |
58 qed_spec_mp "not_Says_to_self"; |
59 Addsimps [not_Says_to_self]; |
59 Addsimps [not_Says_to_self]; |
60 AddSEs [not_Says_to_self RSN (2, rev_notE)]; |
60 AddSEs [not_Says_to_self RSN (2, rev_notE)]; |
61 |
61 |
62 |
62 |
63 (*Forwarding Lemma for reasoning about the encrypted portion of message Kb3*) |
63 (*Forwarding Lemma for reasoning about the encrypted portion of message Kb3*) |
64 goal thy "!!evs. Says S A (Crypt KA {|Timestamp, B, K, X|}) : set evs \ |
64 Goal "!!evs. Says S A (Crypt KA {|Timestamp, B, K, X|}) : set evs \ |
65 \ ==> X : parts (spies evs)"; |
65 \ ==> X : parts (spies evs)"; |
66 by (Blast_tac 1); |
66 by (Blast_tac 1); |
67 qed "Kb3_msg_in_parts_spies"; |
67 qed "Kb3_msg_in_parts_spies"; |
68 |
68 |
69 goal thy |
69 Goal |
70 "!!evs. Says Server A (Crypt (shrK A) {|Timestamp, B, K, X|}) : set evs \ |
70 "!!evs. Says Server A (Crypt (shrK A) {|Timestamp, B, K, X|}) : set evs \ |
71 \ ==> K : parts (spies evs)"; |
71 \ ==> K : parts (spies evs)"; |
72 by (Blast_tac 1); |
72 by (Blast_tac 1); |
73 qed "Oops_parts_spies"; |
73 qed "Oops_parts_spies"; |
74 |
74 |
79 forward_tac [Kb3_msg_in_parts_spies] (i+4) THEN |
79 forward_tac [Kb3_msg_in_parts_spies] (i+4) THEN |
80 prove_simple_subgoals_tac i; |
80 prove_simple_subgoals_tac i; |
81 |
81 |
82 |
82 |
83 (*Spy never sees another agent's shared key! (unless it's bad at start)*) |
83 (*Spy never sees another agent's shared key! (unless it's bad at start)*) |
84 goal thy |
84 Goal |
85 "!!evs. evs : kerberos_ban ==> (Key (shrK A) : parts (spies evs)) = (A : bad)"; |
85 "!!evs. evs : kerberos_ban ==> (Key (shrK A) : parts (spies evs)) = (A : bad)"; |
86 by (parts_induct_tac 1); |
86 by (parts_induct_tac 1); |
87 by (ALLGOALS Blast_tac); |
87 by (ALLGOALS Blast_tac); |
88 qed "Spy_see_shrK"; |
88 qed "Spy_see_shrK"; |
89 Addsimps [Spy_see_shrK]; |
89 Addsimps [Spy_see_shrK]; |
90 |
90 |
91 |
91 |
92 goal thy |
92 Goal |
93 "!!evs. evs : kerberos_ban ==> (Key (shrK A) : analz (spies evs)) = (A : bad)"; |
93 "!!evs. evs : kerberos_ban ==> (Key (shrK A) : analz (spies evs)) = (A : bad)"; |
94 by Auto_tac; |
94 by Auto_tac; |
95 qed "Spy_analz_shrK"; |
95 qed "Spy_analz_shrK"; |
96 Addsimps [Spy_analz_shrK]; |
96 Addsimps [Spy_analz_shrK]; |
97 |
97 |
98 goal thy "!!A. [| Key (shrK A) : parts (spies evs); \ |
98 Goal "!!A. [| Key (shrK A) : parts (spies evs); \ |
99 \ evs : kerberos_ban |] ==> A:bad"; |
99 \ evs : kerberos_ban |] ==> A:bad"; |
100 by (blast_tac (claset() addDs [Spy_see_shrK]) 1); |
100 by (blast_tac (claset() addDs [Spy_see_shrK]) 1); |
101 qed "Spy_see_shrK_D"; |
101 qed "Spy_see_shrK_D"; |
102 |
102 |
103 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D); |
103 bind_thm ("Spy_analz_shrK_D", analz_subset_parts RS subsetD RS Spy_see_shrK_D); |
104 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D]; |
104 AddSDs [Spy_see_shrK_D, Spy_analz_shrK_D]; |
105 |
105 |
106 |
106 |
107 (*Nobody can have used non-existent keys!*) |
107 (*Nobody can have used non-existent keys!*) |
108 goal thy "!!evs. evs : kerberos_ban ==> \ |
108 Goal "!!evs. evs : kerberos_ban ==> \ |
109 \ Key K ~: used evs --> K ~: keysFor (parts (spies evs))"; |
109 \ Key K ~: used evs --> K ~: keysFor (parts (spies evs))"; |
110 by (parts_induct_tac 1); |
110 by (parts_induct_tac 1); |
111 (*Fake*) |
111 (*Fake*) |
112 by (blast_tac (claset() addSDs [keysFor_parts_insert]) 1); |
112 by (blast_tac (claset() addSDs [keysFor_parts_insert]) 1); |
113 (*Kb2, Kb3, Kb4*) |
113 (*Kb2, Kb3, Kb4*) |
122 |
122 |
123 |
123 |
124 (** Lemmas concerning the form of items passed in messages **) |
124 (** Lemmas concerning the form of items passed in messages **) |
125 |
125 |
126 (*Describes the form of K, X and K' when the Server sends this message.*) |
126 (*Describes the form of K, X and K' when the Server sends this message.*) |
127 goal thy |
127 Goal |
128 "!!evs. [| Says Server A (Crypt K' {|Number Ts, Agent B, Key K, X|}) \ |
128 "!!evs. [| Says Server A (Crypt K' {|Number Ts, Agent B, Key K, X|}) \ |
129 \ : set evs; evs : kerberos_ban |] \ |
129 \ : set evs; evs : kerberos_ban |] \ |
130 \ ==> K ~: range shrK & \ |
130 \ ==> K ~: range shrK & \ |
131 \ X = (Crypt (shrK B) {|Number Ts, Agent A, Key K|}) & \ |
131 \ X = (Crypt (shrK B) {|Number Ts, Agent A, Key K|}) & \ |
132 \ K' = shrK A"; |
132 \ K' = shrK A"; |
139 (*If the encrypted message appears then it originated with the Server |
139 (*If the encrypted message appears then it originated with the Server |
140 PROVIDED that A is NOT compromised! |
140 PROVIDED that A is NOT compromised! |
141 |
141 |
142 This shows implicitly the FRESHNESS OF THE SESSION KEY to A |
142 This shows implicitly the FRESHNESS OF THE SESSION KEY to A |
143 *) |
143 *) |
144 goal thy |
144 Goal |
145 "!!evs. [| Crypt (shrK A) {|Number Ts, Agent B, Key K, X|} \ |
145 "!!evs. [| Crypt (shrK A) {|Number Ts, Agent B, Key K, X|} \ |
146 \ : parts (spies evs); \ |
146 \ : parts (spies evs); \ |
147 \ A ~: bad; evs : kerberos_ban |] \ |
147 \ A ~: bad; evs : kerberos_ban |] \ |
148 \ ==> Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
148 \ ==> Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
149 \ : set evs"; |
149 \ : set evs"; |
153 qed "A_trusts_K_by_Kb2"; |
153 qed "A_trusts_K_by_Kb2"; |
154 |
154 |
155 |
155 |
156 (*If the TICKET appears then it originated with the Server*) |
156 (*If the TICKET appears then it originated with the Server*) |
157 (*FRESHNESS OF THE SESSION KEY to B*) |
157 (*FRESHNESS OF THE SESSION KEY to B*) |
158 goal thy |
158 Goal |
159 "!!evs. [| Crypt (shrK B) {|Number Ts, Agent A, Key K|} : parts (spies evs); \ |
159 "!!evs. [| Crypt (shrK B) {|Number Ts, Agent A, Key K|} : parts (spies evs); \ |
160 \ B ~: bad; evs : kerberos_ban |] \ |
160 \ B ~: bad; evs : kerberos_ban |] \ |
161 \ ==> Says Server A \ |
161 \ ==> Says Server A \ |
162 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, \ |
162 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, \ |
163 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|}|}) \ |
163 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|}|}) \ |
169 |
169 |
170 |
170 |
171 (*EITHER describes the form of X when the following message is sent, |
171 (*EITHER describes the form of X when the following message is sent, |
172 OR reduces it to the Fake case. |
172 OR reduces it to the Fake case. |
173 Use Says_Server_message_form if applicable.*) |
173 Use Says_Server_message_form if applicable.*) |
174 goal thy |
174 Goal |
175 "!!evs. [| Says S A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
175 "!!evs. [| Says S A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
176 \ : set evs; \ |
176 \ : set evs; \ |
177 \ evs : kerberos_ban |] \ |
177 \ evs : kerberos_ban |] \ |
178 \ ==> (K ~: range shrK & X = (Crypt (shrK B) {|Number Ts, Agent A, Key K|}))\ |
178 \ ==> (K ~: range shrK & X = (Crypt (shrK B) {|Number Ts, Agent A, Key K|}))\ |
179 \ | X : analz (spies evs)"; |
179 \ | X : analz (spies evs)"; |
204 ****) |
204 ****) |
205 |
205 |
206 |
206 |
207 (** Session keys are not used to encrypt other session keys **) |
207 (** Session keys are not used to encrypt other session keys **) |
208 |
208 |
209 goal thy |
209 Goal |
210 "!!evs. evs : kerberos_ban ==> \ |
210 "!!evs. evs : kerberos_ban ==> \ |
211 \ ALL K KK. KK <= Compl (range shrK) --> \ |
211 \ ALL K KK. KK <= Compl (range shrK) --> \ |
212 \ (Key K : analz (Key``KK Un (spies evs))) = \ |
212 \ (Key K : analz (Key``KK Un (spies evs))) = \ |
213 \ (K : KK | Key K : analz (spies evs))"; |
213 \ (K : KK | Key K : analz (spies evs))"; |
214 by (etac kerberos_ban.induct 1); |
214 by (etac kerberos_ban.induct 1); |
220 (*Fake*) |
220 (*Fake*) |
221 by (spy_analz_tac 1); |
221 by (spy_analz_tac 1); |
222 qed_spec_mp "analz_image_freshK"; |
222 qed_spec_mp "analz_image_freshK"; |
223 |
223 |
224 |
224 |
225 goal thy |
225 Goal |
226 "!!evs. [| evs : kerberos_ban; KAB ~: range shrK |] ==> \ |
226 "!!evs. [| evs : kerberos_ban; KAB ~: range shrK |] ==> \ |
227 \ Key K : analz (insert (Key KAB) (spies evs)) = \ |
227 \ Key K : analz (insert (Key KAB) (spies evs)) = \ |
228 \ (K = KAB | Key K : analz (spies evs))"; |
228 \ (K = KAB | Key K : analz (spies evs))"; |
229 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1); |
229 by (asm_simp_tac (analz_image_freshK_ss addsimps [analz_image_freshK]) 1); |
230 qed "analz_insert_freshK"; |
230 qed "analz_insert_freshK"; |
231 |
231 |
232 |
232 |
233 (** The session key K uniquely identifies the message **) |
233 (** The session key K uniquely identifies the message **) |
234 |
234 |
235 goal thy |
235 Goal |
236 "!!evs. evs : kerberos_ban ==> \ |
236 "!!evs. evs : kerberos_ban ==> \ |
237 \ EX A' Ts' B' X'. ALL A Ts B X. \ |
237 \ EX A' Ts' B' X'. ALL A Ts B X. \ |
238 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
238 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
239 \ : set evs \ |
239 \ : set evs \ |
240 \ --> A=A' & Ts=Ts' & B=B' & X=X'"; |
240 \ --> A=A' & Ts=Ts' & B=B' & X=X'"; |
246 by (REPEAT (ares_tac [refl,exI,impI,conjI] 2)); |
246 by (REPEAT (ares_tac [refl,exI,impI,conjI] 2)); |
247 by (blast_tac (claset() delrules [conjI]) 1); |
247 by (blast_tac (claset() delrules [conjI]) 1); |
248 val lemma = result(); |
248 val lemma = result(); |
249 |
249 |
250 (*In messages of this form, the session key uniquely identifies the rest*) |
250 (*In messages of this form, the session key uniquely identifies the rest*) |
251 goal thy |
251 Goal |
252 "!!evs. [| Says Server A \ |
252 "!!evs. [| Says Server A \ |
253 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) : set evs; \ |
253 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) : set evs; \ |
254 \ Says Server A' \ |
254 \ Says Server A' \ |
255 \ (Crypt (shrK A') {|Number Ts', Agent B', Key K, X'|}) : set evs;\ |
255 \ (Crypt (shrK A') {|Number Ts', Agent B', Key K, X'|}) : set evs;\ |
256 \ evs : kerberos_ban |] ==> A=A' & Ts=Ts' & B=B' & X = X'"; |
256 \ evs : kerberos_ban |] ==> A=A' & Ts=Ts' & B=B' & X = X'"; |
260 |
260 |
261 (** Lemma: the session key sent in msg Kb2 would be EXPIRED |
261 (** Lemma: the session key sent in msg Kb2 would be EXPIRED |
262 if the spy could see it! |
262 if the spy could see it! |
263 **) |
263 **) |
264 |
264 |
265 goal thy |
265 Goal |
266 "!!evs. [| A ~: bad; B ~: bad; evs : kerberos_ban |] \ |
266 "!!evs. [| A ~: bad; B ~: bad; evs : kerberos_ban |] \ |
267 \ ==> Says Server A \ |
267 \ ==> Says Server A \ |
268 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, \ |
268 \ (Crypt (shrK A) {|Number Ts, Agent B, Key K, \ |
269 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|}|})\ |
269 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|}|})\ |
270 \ : set evs --> \ |
270 \ : set evs --> \ |
292 |
292 |
293 (** CONFIDENTIALITY for the SERVER: |
293 (** CONFIDENTIALITY for the SERVER: |
294 Spy does not see the keys sent in msg Kb2 |
294 Spy does not see the keys sent in msg Kb2 |
295 as long as they have NOT EXPIRED |
295 as long as they have NOT EXPIRED |
296 **) |
296 **) |
297 goal thy |
297 Goal |
298 "!!evs. [| Says Server A \ |
298 "!!evs. [| Says Server A \ |
299 \ (Crypt K' {|Number T, Agent B, Key K, X|}) : set evs; \ |
299 \ (Crypt K' {|Number T, Agent B, Key K, X|}) : set evs; \ |
300 \ ~ Expired T evs; \ |
300 \ ~ Expired T evs; \ |
301 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
301 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
302 \ |] ==> Key K ~: analz (spies evs)"; |
302 \ |] ==> Key K ~: analz (spies evs)"; |
310 WOULD HOLD ONLY IF AN OOPS OCCURRED! ---> Nothing to prove! ****) |
310 WOULD HOLD ONLY IF AN OOPS OCCURRED! ---> Nothing to prove! ****) |
311 |
311 |
312 |
312 |
313 (** CONFIDENTIALITY for ALICE: **) |
313 (** CONFIDENTIALITY for ALICE: **) |
314 (** Also A_trusts_K_by_Kb2 RS Confidentiality_S **) |
314 (** Also A_trusts_K_by_Kb2 RS Confidentiality_S **) |
315 goal thy |
315 Goal |
316 "!!evs. [| Crypt (shrK A) {|Number T, Agent B, Key K, X|} : parts (spies evs);\ |
316 "!!evs. [| Crypt (shrK A) {|Number T, Agent B, Key K, X|} : parts (spies evs);\ |
317 \ ~ Expired T evs; \ |
317 \ ~ Expired T evs; \ |
318 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
318 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
319 \ |] ==> Key K ~: analz (spies evs)"; |
319 \ |] ==> Key K ~: analz (spies evs)"; |
320 by (blast_tac (claset() addSDs [A_trusts_K_by_Kb2, Confidentiality_S]) 1); |
320 by (blast_tac (claset() addSDs [A_trusts_K_by_Kb2, Confidentiality_S]) 1); |
321 qed "Confidentiality_A"; |
321 qed "Confidentiality_A"; |
322 |
322 |
323 |
323 |
324 (** CONFIDENTIALITY for BOB: **) |
324 (** CONFIDENTIALITY for BOB: **) |
325 (** Also B_trusts_K_by_Kb3 RS Confidentiality_S **) |
325 (** Also B_trusts_K_by_Kb3 RS Confidentiality_S **) |
326 goal thy |
326 Goal |
327 "!!evs. [| Crypt (shrK B) {|Number Tk, Agent A, Key K|} \ |
327 "!!evs. [| Crypt (shrK B) {|Number Tk, Agent A, Key K|} \ |
328 \ : parts (spies evs); \ |
328 \ : parts (spies evs); \ |
329 \ ~ Expired Tk evs; \ |
329 \ ~ Expired Tk evs; \ |
330 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
330 \ A ~: bad; B ~: bad; evs : kerberos_ban \ |
331 \ |] ==> Key K ~: analz (spies evs)"; |
331 \ |] ==> Key K ~: analz (spies evs)"; |
332 by (blast_tac (claset() addSDs [B_trusts_K_by_Kb3, |
332 by (blast_tac (claset() addSDs [B_trusts_K_by_Kb3, |
333 Confidentiality_S]) 1); |
333 Confidentiality_S]) 1); |
334 qed "Confidentiality_B"; |
334 qed "Confidentiality_B"; |
335 |
335 |
336 |
336 |
337 goal thy |
337 Goal |
338 "!!evs. [| B ~: bad; evs : kerberos_ban |] \ |
338 "!!evs. [| B ~: bad; evs : kerberos_ban |] \ |
339 \ ==> Key K ~: analz (spies evs) --> \ |
339 \ ==> Key K ~: analz (spies evs) --> \ |
340 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
340 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
341 \ : set evs --> \ |
341 \ : set evs --> \ |
342 \ Crypt K (Number Ta) : parts (spies evs) --> \ |
342 \ Crypt K (Number Ta) : parts (spies evs) --> \ |
365 Crypt_Spy_analz_bad]) 1); |
365 Crypt_Spy_analz_bad]) 1); |
366 val lemma_B = result(); |
366 val lemma_B = result(); |
367 |
367 |
368 |
368 |
369 (*AUTHENTICATION OF B TO A*) |
369 (*AUTHENTICATION OF B TO A*) |
370 goal thy |
370 Goal |
371 "!!evs. [| Crypt K (Number Ta) : parts (spies evs); \ |
371 "!!evs. [| Crypt K (Number Ta) : parts (spies evs); \ |
372 \ Crypt (shrK A) {|Number Ts, Agent B, Key K, X|} \ |
372 \ Crypt (shrK A) {|Number Ts, Agent B, Key K, X|} \ |
373 \ : parts (spies evs); \ |
373 \ : parts (spies evs); \ |
374 \ ~ Expired Ts evs; \ |
374 \ ~ Expired Ts evs; \ |
375 \ A ~: bad; B ~: bad; evs : kerberos_ban |] \ |
375 \ A ~: bad; B ~: bad; evs : kerberos_ban |] \ |
378 addSIs [lemma_B RS mp RS mp RS mp] |
378 addSIs [lemma_B RS mp RS mp RS mp] |
379 addSEs [Confidentiality_S RSN (2,rev_notE)]) 1); |
379 addSEs [Confidentiality_S RSN (2,rev_notE)]) 1); |
380 qed "Authentication_B"; |
380 qed "Authentication_B"; |
381 |
381 |
382 |
382 |
383 goal thy |
383 Goal |
384 "!!evs. [| A ~: bad; B ~: bad; evs : kerberos_ban |] ==> \ |
384 "!!evs. [| A ~: bad; B ~: bad; evs : kerberos_ban |] ==> \ |
385 \ Key K ~: analz (spies evs) --> \ |
385 \ Key K ~: analz (spies evs) --> \ |
386 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
386 \ Says Server A (Crypt (shrK A) {|Number Ts, Agent B, Key K, X|}) \ |
387 \ : set evs --> \ |
387 \ : set evs --> \ |
388 \ Crypt K {|Agent A, Number Ta|} : parts (spies evs) -->\ |
388 \ Crypt K {|Agent A, Number Ta|} : parts (spies evs) -->\ |
402 by (blast_tac (claset() addDs [A_trusts_K_by_Kb2, unique_session_keys]) 1); |
402 by (blast_tac (claset() addDs [A_trusts_K_by_Kb2, unique_session_keys]) 1); |
403 val lemma_A = result(); |
403 val lemma_A = result(); |
404 |
404 |
405 |
405 |
406 (*AUTHENTICATION OF A TO B*) |
406 (*AUTHENTICATION OF A TO B*) |
407 goal thy |
407 Goal |
408 "!!evs. [| Crypt K {|Agent A, Number Ta|} : parts (spies evs); \ |
408 "!!evs. [| Crypt K {|Agent A, Number Ta|} : parts (spies evs); \ |
409 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|} \ |
409 \ Crypt (shrK B) {|Number Ts, Agent A, Key K|} \ |
410 \ : parts (spies evs); \ |
410 \ : parts (spies evs); \ |
411 \ ~ Expired Ts evs; \ |
411 \ ~ Expired Ts evs; \ |
412 \ A ~: bad; B ~: bad; evs : kerberos_ban |] \ |
412 \ A ~: bad; B ~: bad; evs : kerberos_ban |] \ |