Theory Noninterference

Up to index of Isabelle/HOL/NI

theory Noninterference = Generics:

(*  Title:      NI/Noninterference.thy
    Id:         $Id: Noninterference.thy,v 1.15 2004/03/03 16:22:59 dvo Exp $
    Author:     David von Oheimb
    License:    (C) 2003 Siemens AG; any non-commercial use is granted

*)
header {* Noninterference *}
(*<*)
theory Noninterference = Generics:

(*>*)
subsection "purging"

consts gen_purge :: "sourcef => domain => action list => action list" 
primrec 
  Nil : "gen_purge sf u []     = []"
  Cons: "gen_purge sf u (a#as) = (if dom a ∈ sf (a#as) u then [a] else []) 
                                 @ gen_purge sf u as"

constdefs --{* also for transitive policies *}
  ipurge :: "domain => action list => action list" 
 "ipurge ≡ gen_purge sources"
lemma sources_ipurge(*<*) [simp](*>*): "sources (ipurge u as) u = sources as u"
(*<*)
by (unfold sources_def, induct "as", auto simp add: sources_def ipurge_def gen_chain.Cons)

lemma sources_Cons_ipurge: "sources (a # ipurge u as) u = sources (a#as) u"
by (simp add: sources_Cons)

lemma sources_ipurgeD: 
  "v ∈ sources (ipurge u as) u ==> v ∈ sources as u"
by (simp)

lemma ipurge_Nil [simp]: "ipurge u [] = []"
by (simp add: ipurge_def)

lemma ipurge_Cons [simp]: "ipurge u (a#as) = (if dom a ∈ sources (a#as) u
                          then [a] else []) @ ipurge u as"
by (simp add: ipurge_def)

lemma Nil_ipurge_sourcesD [rule_format]: 
  "[] = ipurge u bs --> x ∈ sources bs u --> x = u"
apply (induct "bs")
apply  (auto simp add: ipurge_def sources_Cons)
done

lemma Cons_ipurge_sourcesD: 
 "∀bs. ipurge u as = ipurge u bs --> sources as u = sources bs u ==>
  a # ipurge u as = ipurge u bs --> sources (a # as) u = sources bs u"
apply (induct "bs")
apply  (auto elim!: sources_subset_Cons [THEN subsetD])
apply    (drule spec, erule impE, rule refl, 
          simp add: sources_Cons split add: split_if_asm)+
done

lemma ipurge_sources_cong_lemma [rule_format]: 
 "∀bs. ipurge u as = ipurge u bs --> sources as u = sources bs u"
apply (induct "as")
apply  (auto simp add: intro: sources_refl dest: Nil_ipurge_sourcesD)
apply     (blast dest: Cons_ipurge_sourcesD)
apply    (blast dest: Cons_ipurge_sourcesD)
apply  (auto simp add: sources_Cons split add: split_if_asm)
done
(*>*)
lemma ipurge_sources_cong: 
  "ipurge u as = ipurge u bs ==> sources as u = sources bs u"
(*<*)
by (erule ipurge_sources_cong_lemma)
(*>*)
lemma ipurge_idempotent(*<*) [simp](*>*): "ipurge u (ipurge u as) = ipurge u as"
(*<*)
apply (induct "as")
apply (simp_all)
apply clarify
apply (erule swap)
apply (simp add: dom_in_sources_Cons_eq_lemma)
done
(*>*)

constdefs --{* specical case of @{term ipurge} for transitive policies *}
  tpurge   :: "domain => action list => action list"
 "tpurge ≡ gen_purge tsources"
lemma tpurge_idempotent(*<*) [simp](*>*): "tpurge u (tpurge u as) = tpurge u as"
(*<*)
by (induct "as", simp_all add: tpurge_def tsources_def)
(*>*)
lemma "tpurge u = filter (λa. (dom a \<leadsto> u))" 
(*<*)
by (rule ext, induct_tac "x", auto simp add: tpurge_def tsources_def)
(*>*)
lemma (in policy_trans) tpurge_conincides: "tpurge = ipurge"
(*<*)
apply (unfold ipurge_def tpurge_def)
apply (rule ext)+
apply (induct_tac "xa")
apply  (simp_all only: gen_purge.Nil gen_purge.Cons 
                 tsources_def dom_in_sources_Cons_eq mem_Collect_eq)
done
(*>*)
subsection "the deterministic case"

subsubsection "general version"

constdefs 
  noninterference :: "bool"
 "noninterference ≡ ∀as u. s0 ≅as,u,ipurge u as≅ s0"

constdefs --{* common structure of @{term "noninterference"} and @{text "noninfluence"} *}
  gen_noninterference :: "sourcef => bool"
 "gen_noninterference sf ≡  
  ∀u as s t. s ≈sf as u≈ t --> run as s ∼u∼ run (ipurge u as) t"

lemma output_consistent_and_gen_noninterference_implies_noninterference:
  "output_consistent ==> gen_noninterference sf ==> noninterference"
(*<*)
apply (simp add: gen_noninterference_def noninterference_def)
apply (blast intro: gen_uwr_s0 dest: output_consistentD obs_equivI)
done
(*>*)

constdefs 
  local_respect_left :: "bool"
 "local_respect_left ≡ ∀a u s t. dom a \<notleadsto> u --> s ∼u∼ t --> step a s ∼u∼ t"

  local_respect_right :: "bool"
 "local_respect_right ≡ ∀a u s t. dom a \<notleadsto> u --> s ∼u∼ t --> s ∼u∼ step a t"

  local_respect :: "bool"
 "local_respect ≡ local_respect_left ∧ local_respect_right"
(*<*)
lemma local_respect_leftD: 
  "[|local_respect_left; dom a \<notleadsto> u; s ∼u∼ t|] ==> step a s ∼u∼ t"
by (unfold local_respect_left_def, blast)

lemma local_respect_rightD: 
  "[|local_respect_right; dom a \<notleadsto> u; s ∼u∼ t|] ==> s ∼u∼ step a t"
by (unfold local_respect_right_def, blast)

lemma local_respectD: 
  "local_respect ==> local_respect_left ∧ local_respect_right"
by (unfold local_respect_def, blast)

(*>*)

lemma (in uwr_refl) local_respect_classical: 
  "local_respect ==> ∀a u s. dom a \<notleadsto> u --> s ∼u∼ step a s"
(*<*)
by (blast dest: local_respectD local_respect_rightD intro: uwr_refl)
(*>*)
lemma (in uwr_trans) classical_local_respect: 
  "∀s u t. s ∼u∼ t --> t ∼u∼ s ==>
   ∀a u s. dom a \<notleadsto> u --> s ∼u∼ step a s ==> local_respect"
(*<*)
by (unfold local_respect_def local_respect_left_def local_respect_right_def,
    blast dest: uwr_trans)
(*>*)

lemma local_respect_implies_step_respect: "local_respect ==> step_respect"
(*<*)
apply (unfold step_respect_def)
apply (clarify dest!: local_respectD)
apply (frule (2) local_respect_leftD)
apply (erule (2) local_respect_rightD)
done
(*>*)

lemma gen_noninterference_sources: --{* Rushby's Lemma 5 *}
 "weakly_step_consistent ==> local_respect ==> gen_noninterference sources"
(*<*)
apply (unfold gen_noninterference_def, rule, rule)
apply (induct_tac "as")
apply  (auto split del: split_if)
apply (drule spec, drule spec, erule mp)
apply (auto)
apply  (drule local_respect_implies_step_respect)
apply  (erule (2) sources_unwinding_step)
apply (rule gen_uwr_uwr)
apply  (erule sources_uwr_ConsD [THEN conjunct2])
apply (blast dest: local_respectD local_respect_leftD sources_trans)
done
(*>*)

theorem noninterference: --{* Rushby's Theorem 7 *}
"[|weakly_step_consistent; local_respect; output_consistent|] ==> noninterference"
(*<*)
by (blast intro: gen_noninterference_sources
    output_consistent_and_gen_noninterference_implies_noninterference)

(*>*)
subsubsection "simple version"

constdefs
 step_consistent :: "bool" --{* new premise @{term "dom a \<leadsto> u"} *}
"step_consistent ≡ ∀a u s t. dom a \<leadsto> u --> s ∼u∼ t --> step a s ∼u∼ step a t"

theorem simple_noninterference: --{* Rushby's Theorem 1 *}
 "step_consistent ==> local_respect ==> gen_noninterference singleton"
(*<*)
apply (simp add: gen_noninterference_def, rule, rule)
apply (induct_tac "as")
apply  (auto split del: split_if)
apply (drule spec, drule spec, erule mp)
apply (auto)
apply  (case_tac "dom a \<leadsto> u")
apply   (simp add: step_consistent_def)
apply  (blast 
         dest: local_respect_implies_step_respect [THEN step_respectD])
apply (blast dest: rev_sources_direct local_respectD local_respect_leftD)
done

lemma simple_noninterference_implies_gen_noninterference_sources:
  "gen_noninterference singleton ==> gen_noninterference sources"
by (unfold gen_noninterference_def, 
    blast intro: gen_uwr_mono [OF _ singleton_subset_sources])

(*>*)
subsubsection "strong version"
(*
constdefs
  strong_gen_noninterference :: "sourcef => bool"
 "strong_gen_noninterference sf ≡ ∀u as s t bs. s ≈sf as u≈ t --> 
   gen_purge sf u as = gen_purge sf u bs --> run as s ∼u∼ run bs t"

lemma gen_purge_nilD [rule_format]: "local_respect_right ==> 
  [] = gen_purge sf u bs --> (∀t. s ∼u∼ t --> s ∼u∼ run bs t)"
apply (induct "bs")
apply  (simp_all)
apply (clarify)
apply (drule sym, erule (1) impE)
apply (drule spec, erule mp)
#
apply (blast dest: local_respect_rightD rev_sources_direct)
done

lemma gen_purge_consD [rule_format]: 
 "local_respect_right ==> a # as = ipurge u bs  -->
  (∃bsa bsc. bs = bsa @ a # bsc ∧ (∀t. s ≈sources (a#as) u≈ t --> s ≈sources (a#as) u≈ run bsa t) ∧ as = ipurge u bsc)"
apply (induct "bs") 
apply  (simp_all)
apply (rule conjI)
apply  (clarify, rule_tac x = "[]" in exI, simp)
apply (clarsimp)
apply (rule exI)+
apply (rule conjI)
apply  (rule append_Cons [symmetric])
apply (clarsimp)
apply (drule spec, erule mp)
apply (blast dest: local_respect_rightD rev_sources_trans gen_unwindingD
       intro!: gen_unwindingI)
done

lemma strong_noninterference:
 "weakly_step_consistent ==> local_respect ==> strong_noninterference"
apply (subgoal_tac "∀u as bs s t. ipurge u as = ipurge u bs --> 
                    s ≈sources as u≈ t --> run as s ∼u∼ run bs t")
apply  (unfold strong_noninterference_def, blast)
apply (rule, rule, simp)
apply (frule local_respectD, erule conjE)
apply (induct_tac "as")
apply  (auto)
apply   (erule (2) ipurge_nilD)
apply  (frule (1) ipurge_consD, clarify)
apply  (drule spec, erule (1) impE)
apply  (thin_tac "a # ?as = ipurge u ?bs")
apply  (thin_tac "ipurge u list = ipurge u bsc")
apply  (simp add: sources_Cons_ipurge)
apply  (drule spec, drule spec, erule mp)
apply  (drule spec, erule (1) impE)
apply  (drule local_respect_implies_step_respect)
apply  (blast dest: sources_unwinding_step) 
apply (drule spec, erule impE, rule refl)
apply (drule spec, drule spec, erule mp)
apply (drule sources_unwinding_ConsD [THEN conjunct2])
apply (rule gen_unwindingI)
apply (blast dest: local_respect_leftD gen_unwindingD rev_sources_trans)
done
*)
constdefs
  strong_noninterference :: "bool"
 "strong_noninterference ≡ ∀as u bs. ipurge u as = ipurge u bs --> s0 ≅as,u,bs≅ s0"

lemma strong_noninterference_implies_noninterference:
 "strong_noninterference ==> noninterference"
(*<*)
apply (unfold strong_noninterference_def noninterference_def obs_equiv_def)
apply (clarify)
apply (drule spec)+
apply (erule mp)
apply (simp only: ipurge_idempotent)
done

lemma gen_noninterference_sources_left [rule_format]:
"weakly_step_consistent ==> local_respect ==> 
∀u as s t. s ≈sources as u≈ t --> run (ipurge u as) s ∼u∼ run as t"
apply (rule, rule)
apply (induct_tac "as")
apply  (auto split del: split_if)
apply (drule spec, drule spec, erule mp)
apply (auto)
apply  (drule local_respect_implies_step_respect)
apply  (erule (2) sources_unwinding_step)
apply (rule gen_uwr_uwr)
apply  (erule sources_uwr_ConsD [THEN conjunct2])
apply (blast dest: local_respectD local_respect_rightD 
             intro: sources_trans)
done

lemma strong_noninterference00:
"[|weakly_step_consistent; local_respect; output_consistent|] ==> strong_noninterference"
apply (unfold strong_noninterference_def obs_equiv_def, clarify)
apply (rule trans)
defer 1
apply  (erule output_consistentD)
apply  (erule (1) gen_noninterference_sources_left)
apply  (rule gen_uwr_s0)
apply (erule output_consistentD)
apply (drule (1) gen_noninterference_sources)
apply (drule sym)
apply (simp add: gen_noninterference_def gen_uwr_s0)
done

lemma strong_noninterference0:
"output_consistent ==> gen_noninterference sources ==> strong_noninterference"
apply (unfold strong_noninterference_def obs_equiv_def gen_noninterference_def)
apply (clarify)
apply (rule trans)
apply  (erule output_consistentD)
apply  (blast intro: gen_uwr_s0)
apply (rule sym)
apply (erule output_consistentD)
apply (simp add: gen_uwr_s0)
done
(*>*)

lemma ipurge_nilD [rule_format]: "local_respect_right ==> 
  [] = ipurge u bs --> (∀t. s ∼u∼ t --> s ∼u∼ run bs t)"
(*<*)
apply (induct "bs")
apply  (simp_all)
apply (blast intro: sym 
       dest: local_respect_rightD rev_sources_direct)
done

lemma ipurge_consD0 [rule_format]: --{* unused *}
 "local_respect_right ==> a # as = ipurge u bs --> 
   (∃bsa bsc. bs = bsa @ a # bsc ∧ as = ipurge u bsc ∧ 
   (∀t. s ∼u∼ t --> s ∼u∼ run bsa t))"
apply (induct "bs") 
apply  (simp_all)
apply (rule conjI)
apply  (clarify, rule_tac x = "[]" in exI, simp)
apply (clarsimp)
apply (rule exI)+
apply (rule conjI)
apply  (rule append_Cons [symmetric])
apply (simp)
apply (blast dest: local_respect_rightD rev_sources_direct)
done
(*>*)

lemma ipurge_consD [rule_format]: 
 "local_respect_right ==> a # as = ipurge u bs  -->
  (∃bsa bsc. bs = bsa @ a # bsc ∧ as = ipurge u bsc ∧ 
(∀t. s ≈sources (a#as) u≈ t --> s ≈sources (a#as) u≈ run bsa t))"
(*<*)
apply (induct "bs") 
apply  (simp_all)
apply (rule conjI)
apply  (clarify, rule_tac x = "[]" in exI, simp)
apply (clarsimp)
apply (rule exI)+
apply (rule conjI)
apply  (rule append_Cons [symmetric])
apply (clarsimp)
apply (drule spec, erule mp)
apply (drule rev_sources_trans)
apply (blast dest: local_respect_rightD gen_uwrD intro!: gen_uwrI)
done
(*>*)

theorem strong_noninterference:
 "[|weakly_step_consistent; local_respect; output_consistent|] ==> strong_noninterference"
(*<*)
apply (subgoal_tac "∀u as bs s t. ipurge u as = ipurge u bs --> 
                    s ≈sources as u≈ t --> run as s ∼u∼ run bs t")
apply  (unfold strong_noninterference_def obs_equiv_def)
apply  (fast elim!: output_consistentD intro: gen_uwr_s0)
apply (rule, rule, simp)
apply (frule local_respectD)
apply (induct_tac "as")
apply  (auto)
apply   (erule (2) ipurge_nilD)
apply  (frule (1) ipurge_consD, clarify)
apply  (drule spec, erule (1) impE)
apply  (thin_tac "a # ?as = ipurge u ?bs")
apply  (thin_tac "ipurge u list = ipurge u bsc")
apply  (simp add: sources_Cons_ipurge)
apply  (drule spec, drule spec, erule mp)
apply  (drule spec, erule (1) impE)
apply  (drule local_respect_implies_step_respect)
apply  (blast dest: sources_unwinding_step) 
apply (drule spec, erule impE, rule refl)
apply (drule spec, drule spec, erule mp)
apply (drule sources_uwr_ConsD [THEN conjunct2])
apply (rule gen_uwrI)
apply (blast dest: local_respect_leftD gen_uwrD rev_sources_trans)
done
(*>*)

subsubsection "access control interpretation"

typedecl "name"
typedecl "value"
consts contents :: "state => name => value"

consts observe :: "domain => name set"
       alter   :: "domain => name set"

defs uwr_def: "s ∼u∼ t ≡ ∀n∈observe u. contents s n = contents t n"

locale canonical_output = --{* special case: all observable values are output *}
  fixes value2output :: "value => output" --{* type coercion *}
  assumes output_def: 
     "output u s ≡ {value2output (contents s n) |n. n ∈ observe u}"
lemma (in canonical_output) canonical_output_consistent: "output_consistent"
(*<*)
apply (auto simp add: output_consistent_def uwr_def output_def)
apply (rule_tac x = "n" in exI)
apply (simp)
done
(*>*)

constdefs --{* Reference Monitor Assumptions *}
  RMA1 :: "bool"
 "RMA1 ≡ output_consistent"

  RMA2 :: "bool" --{* new premises @{term "dom a \<leadsto> u"}, @{term "s ∼u∼ t"}, and @{term "n ∈ observe u"} *}
 "RMA2 ≡ ∀a u s t n. s ∼dom a∼ t --> dom a \<leadsto> u --> s ∼u∼ t --> n ∈ observe u --> 
                      (contents (step a s) n ≠ contents s n ∨ 
                       contents (step a t) n ≠ contents t n) --> 
                       contents (step a s) n = contents (step a t) n"

  RMA3 :: "bool"
 "RMA3 ≡ ∀a s n. contents (step a s) n ≠ contents s n --> n ∈ alter (dom a)"

  AC_policy_consistent :: "bool"
 "AC_policy_consistent ≡ ∀u v. alter u ∩ observe v ≠ {} --> u \<leadsto> v"
(*<*)
lemma AC_policy_consistent_revD: 
  "AC_policy_consistent ==> n ∈ observe v ==> u \<notleadsto> v ==> n ∉ alter u"
by (unfold AC_policy_consistent_def, blast)

lemma AC_unwinding_weakly_step_consistentI:
  "(!!a u s t n. [|dom a \<leadsto> u; s ∼dom a∼ t; s ∼u∼ t; n ∈ observe u; 
                  contents (step a s) n ≠ contents s n ∨ 
                  contents (step a t) n ≠ contents t n|] ==> 
                  contents (step a s) n = contents (step a t) n)
 ==> weakly_step_consistent"
apply (clarsimp simp add: weakly_step_consistent_def uwr_def)
apply (case_tac "contents (step a s) n = contents s n ∧ 
                 contents (step a t) n = contents t n")
apply  (auto)
done
(*>*)

lemma RMA2_implies_weakly_step_consistent: "RMA2 ==> weakly_step_consistent"
(*<*)
by (rule AC_unwinding_weakly_step_consistentI, simp add: RMA2_def)
(*>*)

lemma RMA3_AC_policy_consistent_implies_local_respect: 
  "RMA3 ==> AC_policy_consistent ==> local_respect"
(*<*)
apply (unfold RMA3_def uwr_def
       local_respect_def local_respect_left_def local_respect_right_def)
apply (safe)
apply  (drule (1) bspec, drule sym, simp, blast dest: AC_policy_consistent_revD)
apply (drule (1) bspec, simp, blast dest: sym AC_policy_consistent_revD)
done
(*>*)

theorem access_control_secure: 
  "[|RMA1; RMA2; RMA3; AC_policy_consistent|] ==> noninterference"
(*<*)
by (auto simp: RMA1_def 
 intro!: noninterference RMA2_implies_weakly_step_consistent
 elim: RMA3_AC_policy_consistent_implies_local_respect)

(*>*)
subsection "the nondeterministic case"

constdefs 
  Noninterference :: "bool"
 "Noninterference ≡ ∀as u bs. ipurge u as = ipurge u bs --> s0 \<lesssim>as,u,bs\<lesssim> s0"

  gen_Noninterference :: "sourcef => bool"
 "gen_Noninterference sf ≡ ∀as bs s s' u t. ipurge u as = ipurge u bs --> 
         (s, s') ∈ Run as --> s ≈sf as u≈ t --> 
   (∃t'. (t, t') ∈ Run bs ∧ s' ∼u∼ t')"
lemma 
  output_consistent_and_gen_Noninterference_implies_Noninterference:
  "output_consistent ==> gen_Noninterference sf ==> Noninterference"
(*<*)
apply (unfold Noninterference_def gen_Noninterference_def)
apply (blast intro: gen_uwr_s0 dest: output_consistentD obs_POI)
done
(*>*)
subsubsection "simple version"

constdefs 
  Local_respect_left :: "bool"
 "Local_respect_left ≡ ∀a u s t s'. dom a \<notleadsto> u --> 
  s ∼u∼ t --> (s, s') ∈ Step a --> s' ∼u∼ t"

  Local_respect_right :: "bool"
 "Local_respect_right ≡ ∀a u s t. dom a \<notleadsto> u --> 
  s ∼u∼ t --> (∃t'. (t, t') ∈ Step a ∧ s ∼u∼ t')"
(*<*)
lemma Local_respect_leftD: 
 "[|Local_respect_left; dom a \<notleadsto> u; (s, s') ∈ Step a; s ∼u∼ t|] ==> s' ∼u∼ t" 
by (unfold Local_respect_left_def, blast)

lemma Local_respect_rightD: 
  "[|Local_respect_right; dom a \<notleadsto> u; s ∼u∼ t|] ==> ∃t'. (t, t') ∈ Step a ∧ s ∼u∼ t'"
by (unfold Local_respect_right_def, blast)
(*>*)

lemma Local_respect_implies_Step_respect:
 "[|Local_respect_left; Local_respect_right|] ==> Step_respect"
(*<*)
by (unfold Step_respect_def, blast dest: Local_respect_leftD Local_respect_rightD)
(*>*)

lemma (in uwr_refl) Local_respect_left_Mantel: 
  "Local_respect_left ==> 
   ∀a u s t s'. dom a \<notleadsto> u --> (s, s') ∈ Step a --> s' ∼u∼ s"
(*<*)
by (blast dest: Local_respect_leftD intro: uwr_refl)
(*>*)

lemma (in uwr_refl) Local_respect_right_Mantel: 
  "Local_respect_right ==> 
   ∀a u s t. dom a \<notleadsto> u --> (∃t'. (t, t') ∈ Step a ∧ t ∼u∼ t')"
(*<*)
by (blast dest: Local_respect_rightD intro: uwr_refl)
(*>*)

lemma (in uwr_trans) Mantel_Local_respect_left: 
  "∀a u s t s'. dom a \<notleadsto> u --> (s, s') ∈ Step a --> s' ∼u∼ s ==> 
   Local_respect_left"
(*<*)
by (unfold Local_respect_left_def, blast dest: uwr_trans)
(*>*)

lemma (in uwr_trans) Mantel_Local_respect_right: 
  "∀a u s t. dom a \<notleadsto> u --> (∃t'. (t, t') ∈ Step a ∧ t ∼u∼ t') ==> 
   Local_respect_right"
(*<*)
by (unfold Local_respect_right_def, blast dest: uwr_trans)
(*>*)

lemma ipurge_NilD [rule_format]: "Local_respect_right ==> 
  [] = ipurge u bs --> (∀t. s ∼u∼ t --> (∃t'. (t, t') ∈ Run bs ∧ s ∼u∼ t'))"
(*<*)
apply (induct "bs")
apply  (simp_all)
apply (blast intro: sym 
       dest: Local_respect_rightD rev_sources_direct)
done
(*>*)

lemma ipurge_ConsD [rule_format]: "Local_respect_right ==> 
  a # as = ipurge u bs --> (∃bsa bsc. bs = bsa @ a # bsc ∧ as = ipurge u bsc ∧
  (∀t. s ∼u∼ t --> (∃ta. (t, ta) ∈ Run bsa ∧ s ∼u∼ ta)))"
(*<*)
apply (induct "bs") 
apply  (simp_all)
apply (rule conjI)
apply  (clarify, rule_tac x = "[]" in exI, simp)
apply (clarsimp)
apply (rule exI)+
apply (rule conjI)
apply  (rule append_Cons [symmetric])
apply (simp)
apply (blast dest: Local_respect_rightD rev_sources_direct)
done

theorem simple_Noninterference_lemma: 
 "Step_consistent ==> Local_respect_left ==> Local_respect_right ==> 
  gen_Noninterference singleton"
apply (subgoal_tac "∀u as s' s bs t. (s, s')∈Run as --> 
                    ipurge u as = ipurge u bs --> s ∼u∼ t --> 
                  (∃t'. (t, t')∈Run bs ∧ s' ∼u∼ t')")
apply  (simp add: gen_Noninterference_def)
apply (rule, rule, rule, simp)
apply (induct_tac "as")
apply (auto split del: split_if)
apply  (fast elim!: ipurge_NilD)
apply (rename_tac sa sb sc bs t)
apply (drule spec, erule (1) impE)
apply (simp split add: split_if_asm)
apply  (frule (1) ipurge_ConsD, clarify)
apply  (drule spec, erule (1) impE)
apply  (thin_tac "a # ?as = ipurge u ?bs")
apply  (thin_tac "ipurge u list = ipurge u bsc")
apply  (simp)
apply  (drule spec, erule (1) impE, clarify)
apply  (drule (1) Local_respect_implies_Step_respect) 
apply  (thin_tac "sa ∼u∼ t")
apply  (drule (3) simple_unwinding_Step, blast)
apply (blast dest: rev_sources_direct Local_respect_leftD)
done
(*>*)

theorem simple_Noninterference: 
 "Step_consistent ==> Local_respect_left ==> Local_respect_right ==> 
  output_consistent ==> Noninterference"
(*<*)
apply (drule (2) simple_Noninterference_lemma)
apply (simp add: Noninterference_def gen_Noninterference_def)
apply (blast intro: uwr_s0 dest: output_consistentD obs_POI)
done
(*>*)

subsubsection "uniform version"

constdefs
  uni_Local_respect_right :: "bool"
 "uni_Local_respect_right ≡ ∀a us s t. ¬(∃u∈us. dom a \<leadsto> u) --> (∃u. u∈us) -->
  s ≈us≈ t --> (∃t'. (t, t') ∈ Step a ∧ s ≈us≈ t')"
 
  uni_Local_respect :: "bool"
 "uni_Local_respect ≡ Local_respect_left ∧ uni_Local_respect_right"

lemma uni_Local_respect_leftD: "[|Local_respect_left; 
  (s, s') ∈ Step a; ¬(∃u∈us. dom a \<leadsto> u); s ≈us≈ t|] ==> s' ≈us≈ t" 
(*<*)
apply (rule gen_uwrI)
apply (drule (1) gen_uwrD)
apply (blast dest: Local_respect_leftD)
done

lemma uni_Local_respect_rightD: 
  "[|uni_Local_respect_right; ¬(∃u∈us. dom a \<leadsto> u); u∈us; s ≈us≈ t|] ==> 
    ∃t'. (t, t') ∈ Step a ∧ s ≈us≈ t'"
by (unfold uni_Local_respect_right_def, blast)

lemma uni_Local_respectD: 
  "uni_Local_respect ==> Local_respect_left ∧ uni_Local_respect_right"
by (unfold uni_Local_respect_def, blast)
(*>*)

lemma uni_Local_respect_right_implies_Local_respect_right: 
  "uni_Local_respect_right ==> Local_respect_right"
(*<*)
apply (unfold Local_respect_right_def uni_Local_respect_right_def, clarify)
apply (drule spec, drule_tac x = "{u}" in spec, auto)
done
(*>*)

lemma uni_Local_respect_implies_uni_Step_respect: 
  "uni_Local_respect ==> uni_Step_respect"
(*<*)
by (unfold uni_Step_respect_def, blast dest: uni_Local_respectD 
    uni_Local_respect_leftD uni_Local_respect_rightD)
(*>*)

lemma uni_ipurge_ConsD [rule_format]: "uni_Local_respect_right ==> 
  a # as = ipurge u bs --> (∃bsa bsc. bs = bsa @ a # bsc ∧ as = ipurge u bsc ∧ 
  (∀t. s ≈sources (a#as) u≈ t --> (∃ta. (t, ta) ∈ Run bsa ∧ s ≈sources (a#as) u≈ ta)))"
(*<*)
apply (induct "bs") 
apply  (simp_all)
apply (rule conjI)
apply  (clarify, rule_tac x = "[]" in exI, simp)
apply (clarsimp)
apply (rule exI)+
apply (rule conjI)
apply  (rule append_Cons [symmetric])
apply (clarsimp)
apply (drule rev_sources_trans)
apply (drule (1) uni_Local_respect_rightD, rule sources_refl, erule asm_rl)
apply (blast)
done
(*>*)

lemma gen_Noninterference_sources: 
 "uni_Step_consistent ==> uni_Local_respect ==> gen_Noninterference sources"
(*<*)
apply (subgoal_tac "∀u as s' s bs t. (s, s')∈Run as --> 
                    ipurge u as = ipurge u bs --> s ≈sources as u≈ t --> 
                  (∃t'. (t, t')∈Run bs ∧ s' ∼u∼ t')")
apply  (unfold gen_Noninterference_def, blast)
apply (rule, rule, rule, simp)
apply (frule uni_Local_respectD, erule conjE)
apply (induct_tac "as")
apply  (auto split del: split_if)
apply  (drule uni_Local_respect_right_implies_Local_respect_right)
apply  (fast elim!: ipurge_NilD)
apply (rename_tac sa sb sc bs t)
apply (drule spec, erule (1) impE)
apply (simp split add: split_if_asm)
apply  (frule (1) uni_ipurge_ConsD, clarify)
apply  (drule spec, erule (1) impE)
apply  (thin_tac "a # ?as = ipurge u ?bs")
apply  (thin_tac "ipurge u list = ipurge u bsc")
apply  (simp add: sources_Cons_ipurge)
apply  (drule spec, erule (1) impE, clarify)
apply  (drule uni_Local_respect_implies_uni_Step_respect)
apply  (thin_tac "sa ≈sources (a # list) u≈ t")
apply  (drule (3) sources_unwinding_Step) 
apply  (blast)
apply (drule spec, erule impE, rule refl) 
apply (drule sources_uwr_ConsD [THEN conjunct2])
apply (blast dest: uni_Local_respect_leftD rev_sources_trans)
done
(*>*)

theorem Noninterference: "uni_Step_consistent ==> 
 uni_Local_respect ==> output_consistent ==> Noninterference"
(*<*)
by (blast intro: gen_Noninterference_sources 
    output_consistent_and_gen_Noninterference_implies_Noninterference)

end
(*>*)

purging

lemma sources_ipurge:

  sources (ipurge u as) u = sources as u

lemma sources_Cons_ipurge:

  sources (a # ipurge u as) u = sources (a # as) u

lemma sources_ipurgeD:

  v ∈ sources (ipurge u as) u ==> v ∈ sources as u

lemma ipurge_Nil:

  ipurge u [] = []

lemma ipurge_Cons:

  ipurge u (a # as) =
  (if dom a ∈ sources (a # as) u then [a] else []) @ ipurge u as

lemma Nil_ipurge_sourcesD:

  [| [] = ipurge u bs; x ∈ sources bs u |] ==> x = u

lemma Cons_ipurge_sourcesD:

bs. ipurge u as = ipurge u bs --> sources as u = sources bs u
  ==> a # ipurge u as = ipurge u bs --> sources (a # as) u = sources bs u

lemma ipurge_sources_cong_lemma:

  ipurge u as = ipurge u bs ==> sources as u = sources bs u

lemma ipurge_sources_cong:

  ipurge u as = ipurge u bs ==> sources as u = sources bs u

lemma ipurge_idempotent:

  ipurge u (ipurge u as) = ipurge u as

lemma tpurge_idempotent:

  tpurge u (tpurge u as) = tpurge u as

lemma

  tpurge u = filter (%a. dom a \<leadsto> u)

lemma tpurge_conincides:

  policy_trans ==> tpurge = ipurge

the deterministic case

general version

lemma output_consistent_and_gen_noninterference_implies_noninterference:

  [| output_consistent; gen_noninterference sf |] ==> noninterference

lemma local_respect_leftD:

  [| local_respect_left; dom a \<notleadsto> u; sut |] ==> step a sut

lemma local_respect_rightD:

  [| local_respect_right; dom a \<notleadsto> u; sut |] ==> su∼ step a t

lemma local_respectD:

  local_respect ==> local_respect_left ∧ local_respect_right

lemma local_respect_classical:

  [| uwr_refl; local_respect |]
  ==> ∀a u s. dom a \<notleadsto> u --> su∼ step a s

lemma classical_local_respect:

  [| uwr_trans; ∀s u t. sut --> tus;
     ∀a u s. dom a \<notleadsto> u --> su∼ step a s |]
  ==> local_respect

lemma local_respect_implies_step_respect:

  local_respect ==> step_respect

lemma gen_noninterference_sources:

  [| weakly_step_consistent; local_respect |] ==> gen_noninterference sources

theorem noninterference:

  [| weakly_step_consistent; local_respect; output_consistent |]
  ==> noninterference

simple version

theorem simple_noninterference:

  [| step_consistent; local_respect |] ==> gen_noninterference singleton

lemma simple_noninterference_implies_gen_noninterference_sources:

  gen_noninterference singleton ==> gen_noninterference sources

strong version

lemma strong_noninterference_implies_noninterference:

  strong_noninterference ==> noninterference

lemma gen_noninterference_sources_left:

  [| weakly_step_consistent; local_respect; s ≈sources as ut |]
  ==> run (ipurge u as) su∼ run as t

lemma strong_noninterference00:

  [| weakly_step_consistent; local_respect; output_consistent |]
  ==> strong_noninterference

lemma strong_noninterference0:

  [| output_consistent; gen_noninterference sources |] ==> strong_noninterference

lemma ipurge_nilD:

  [| local_respect_right; [] = ipurge u bs; sut |] ==> su∼ run bs t

lemma ipurge_consD0:

  [| local_respect_right; a # as = ipurge u bs |]
  ==> ∃bsa bsc.
         bs = bsa @ a # bscas = ipurge u bsc ∧ (∀t. sut --> su∼ run bsa t)

lemma ipurge_consD:

  [| local_respect_right; a # as = ipurge u bs |]
  ==> ∃bsa bsc.
         bs = bsa @ a # bscas = ipurge u bsc ∧
         (∀t. s ≈sources (a # as) ut --> s ≈sources (a # as) u≈ run bsa t)

theorem strong_noninterference:

  [| weakly_step_consistent; local_respect; output_consistent |]
  ==> strong_noninterference

access control interpretation

lemma canonical_output_consistent:

  canonical_output value2output ==> output_consistent

lemma AC_policy_consistent_revD:

  [| AC_policy_consistent; n ∈ observe v; u \<notleadsto> v |] ==> n ∉ alter u

lemma AC_unwinding_weakly_step_consistentI:

  (!!a u s t n.
      [| dom a \<leadsto> u; s ∼dom at; sut; n ∈ observe u;
         Noninterference.contents (step a s) n ≠ Noninterference.contents s n ∨
         Noninterference.contents (step a t) n ≠ Noninterference.contents t n |]
      ==> Noninterference.contents (step a s) n =
          Noninterference.contents (step a t) n)
  ==> weakly_step_consistent

lemma RMA2_implies_weakly_step_consistent:

  RMA2 ==> weakly_step_consistent

lemma RMA3_AC_policy_consistent_implies_local_respect:

  [| RMA3; AC_policy_consistent |] ==> local_respect

theorem access_control_secure:

  [| RMA1; RMA2; RMA3; AC_policy_consistent |] ==> noninterference

the nondeterministic case

lemma output_consistent_and_gen_Noninterference_implies_Noninterference:

  [| output_consistent; gen_Noninterference sf |] ==> Noninterference

simple version

lemma Local_respect_leftD:

  [| Local_respect_left; dom a \<notleadsto> u; (s, s') ∈ Step a; sut |]
  ==> s'ut

lemma Local_respect_rightD:

  [| Local_respect_right; dom a \<notleadsto> u; sut |]
  ==> ∃t'. (t, t') ∈ Step asut'

lemma Local_respect_implies_Step_respect:

  [| Local_respect_left; Local_respect_right |] ==> Step_respect

lemma Local_respect_left_Mantel:

  [| uwr_refl; Local_respect_left |]
  ==> ∀a u s t s'. dom a \<notleadsto> u --> (s, s') ∈ Step a --> s'us

lemma Local_respect_right_Mantel:

  [| uwr_refl; Local_respect_right |]
  ==> ∀a u s t. dom a \<notleadsto> u --> (∃t'. (t, t') ∈ Step atut')

lemma Mantel_Local_respect_left:

  [| uwr_trans;
     ∀a u s t s'. dom a \<notleadsto> u --> (s, s') ∈ Step a --> s'us |]
  ==> Local_respect_left

lemma Mantel_Local_respect_right:

  [| uwr_trans;
     ∀a u s t. dom a \<notleadsto> u --> (∃t'. (t, t') ∈ Step atut') |]
  ==> Local_respect_right

lemma ipurge_NilD:

  [| Local_respect_right; [] = ipurge u bs; sut |]
  ==> ∃t'. (t, t') ∈ Run bssut'

lemma ipurge_ConsD:

  [| Local_respect_right; a # as = ipurge u bs |]
  ==> ∃bsa bsc.
         bs = bsa @ a # bscas = ipurge u bsc ∧ (∀t. sut --> (∃ta. (t, ta) ∈ Run bsasuta))

theorem simple_Noninterference_lemma:

  [| Step_consistent; Local_respect_left; Local_respect_right |]
  ==> gen_Noninterference singleton

theorem simple_Noninterference:

  [| Step_consistent; Local_respect_left; Local_respect_right;
     output_consistent |]
  ==> Noninterference

uniform version

lemma uni_Local_respect_leftD:

  [| Local_respect_left; (s, s') ∈ Step a; ¬ (∃uus. dom a \<leadsto> u);
     sust |]
  ==> s'ust

lemma uni_Local_respect_rightD:

  [| uni_Local_respect_right; ¬ (∃uus. dom a \<leadsto> u); uus; sust |]
  ==> ∃t'. (t, t') ∈ Step asust'

lemma uni_Local_respectD:

  uni_Local_respect ==> Local_respect_left ∧ uni_Local_respect_right

lemma uni_Local_respect_right_implies_Local_respect_right:

  uni_Local_respect_right ==> Local_respect_right

lemma uni_Local_respect_implies_uni_Step_respect:

  uni_Local_respect ==> uni_Step_respect

lemma uni_ipurge_ConsD:

  [| uni_Local_respect_right; a # as = ipurge u bs |]
  ==> ∃bsa bsc.
         bs = bsa @ a # bscas = ipurge u bsc ∧
         (∀t. s ≈sources (a # as) ut -->
              (∃ta. (t, ta) ∈ Run bsas ≈sources (a # as) uta))

lemma gen_Noninterference_sources:

  [| uni_Step_consistent; uni_Local_respect |] ==> gen_Noninterference sources

theorem Noninterference:

  [| uni_Step_consistent; uni_Local_respect; output_consistent |]
  ==> Noninterference