Theory secTypes
theory secTypes
imports Semantics
begin
section ‹Security types›
subsection ‹Security definitions›
datatype secLevel = Low | High
type_synonym typeEnv = "vname ⇀ secLevel"
inductive secExprTyping :: "typeEnv ⇒ expr ⇒ secLevel ⇒ bool" (‹_ ⊢ _ : _›)
where typeVal:  "Γ ⊢ Val V : lev"
  | typeVar:    "Γ Vn = Some lev ⟹ Γ ⊢ Var Vn : lev"
  | typeBinOp1: "⟦Γ ⊢ e1 : Low; Γ ⊢ e2 : Low⟧ ⟹ Γ ⊢ e1 «bop» e2 : Low"
  | typeBinOp2: "⟦Γ ⊢ e1 : High; Γ ⊢ e2 : lev⟧ ⟹ Γ ⊢ e1 «bop» e2 : High"
  | typeBinOp3: "⟦Γ ⊢ e1 : lev; Γ ⊢ e2 : High⟧ ⟹ Γ ⊢ e1 «bop» e2 : High"
inductive secComTyping :: "typeEnv ⇒ secLevel ⇒ com ⇒ bool" (‹_,_ ⊢ _›)
where typeSkip:  "Γ,T ⊢ Skip"
  | typeAssH:    "Γ V = Some High ⟹ Γ,T ⊢ V := e"
  | typeAssL:    "⟦Γ ⊢ e : Low; Γ V = Some Low⟧ ⟹ Γ,Low ⊢ V := e"
  | typeSeq:     "⟦Γ,T ⊢ c1; Γ,T ⊢ c2⟧ ⟹ Γ,T ⊢ c1;;c2"
  | typeWhile:   "⟦Γ ⊢ b : T; Γ,T ⊢ c⟧ ⟹ Γ,T ⊢ while (b) c"
  | typeIf:      "⟦Γ ⊢ b : T; Γ,T ⊢ c1; Γ,T ⊢ c2⟧ ⟹ Γ,T ⊢ if (b) c1 else c2"
  | typeConvert: "Γ,High ⊢ c ⟹ Γ,Low ⊢ c"
subsection ‹Lemmas concerning expressions›
lemma exprTypeable:
  assumes "fv e ⊆ dom Γ" obtains T where "Γ ⊢ e : T"
proof -
  from ‹fv e ⊆ dom Γ› have "∃T. Γ ⊢ e : T"
  proof(induct e)
    case (Val V)
    have "Γ ⊢ Val V : Low" by(rule typeVal)
    thus ?case by (rule exI)
  next
    case (Var V)
    have "V ∈ fv (Var V)" by simp
    with ‹fv (Var V) ⊆ dom Γ› have "V ∈ dom Γ" by simp
    then obtain T where "Γ V = Some T" by auto
    hence "Γ ⊢ Var V : T" by (rule typeVar)
    thus ?case by (rule exI)
  next
    case (BinOp e1 bop e2)
    note IH1 = ‹fv e1 ⊆ dom Γ ⟹ ∃T. Γ ⊢ e1 : T›
    note IH2 = ‹fv e2 ⊆ dom Γ ⟹ ∃T. Γ ⊢ e2 : T›
    from ‹fv (e1 «bop» e2) ⊆ dom Γ›
    have "fv e1 ⊆ dom Γ" and "fv e2 ⊆ dom Γ" by auto
    from IH1[OF ‹fv e1 ⊆ dom Γ›] obtain T1 where "Γ ⊢ e1 : T1" by auto
    from IH2[OF ‹fv e2 ⊆ dom Γ›] obtain T2 where "Γ ⊢ e2 : T2" by auto
    show ?case
    proof (cases T1)
      case Low
      show ?thesis
      proof (cases T2)
        case Low
        with ‹Γ ⊢ e1 : T1› ‹Γ ⊢ e2 : T2› ‹T1 = Low›
        have "Γ ⊢ e1 «bop» e2 : Low" by(simp add:typeBinOp1)
        thus ?thesis by(rule exI)
      next
        case High
        with ‹Γ ⊢ e1 : T1› ‹Γ ⊢ e2 : T2› ‹T1 = Low›
        have "Γ ⊢ e1 «bop» e2 : High" by(simp add:typeBinOp3)
        thus ?thesis by(rule exI)
      qed
    next
      case High
      with ‹Γ ⊢ e1 : T1› ‹Γ ⊢ e2 : T2›
      have "Γ ⊢ e1 «bop» e2 : High" by (simp add: typeBinOp2)
      thus ?thesis by (rule exI)
    qed
  qed
  with that show ?thesis by blast
qed
lemma exprBinopTypeable: 
  assumes "Γ ⊢ e1 «bop» e2 : T"
  shows "(∃T1. Γ ⊢ e1 : T1) ∧ (∃T2. Γ ⊢ e2 : T2)"
using assms by(auto elim:secExprTyping.cases)
lemma exprTypingHigh: 
  assumes "Γ ⊢ e : T" and "x ∈ fv e" and "Γ x = Some High"
  shows "Γ ⊢ e : High"
using assms
proof (induct e arbitrary:T)
  case (Val V) show ?case by (rule typeVal)
next
  case (Var V)
  from ‹x ∈ fv (Var V)› have "x = V" by simp
  with ‹Γ x = Some High› show ?case by(simp add:typeVar)
next
  case (BinOp e1 bop e2)
  note IH1 = ‹⋀T. ⟦Γ ⊢ e1 : T; x ∈ fv e1; Γ x = Some High⟧ ⟹ Γ ⊢ e1 : High›
  note IH2 = ‹⋀T. ⟦Γ ⊢ e2 : T; x ∈ fv e2; Γ x = Some High⟧ ⟹ Γ ⊢ e2 : High›
  from ‹Γ ⊢ e1 «bop» e2 : T› 
  have T:"(∃T1. Γ ⊢ e1 : T1) ∧ (∃T2. Γ ⊢ e2 : T2)" by (auto intro!:exprBinopTypeable)
  then obtain T1 where "Γ ⊢ e1 : T1" by auto
  from T obtain T2 where "Γ ⊢ e2 : T2" by auto
  from ‹x ∈ fv (e1 «bop» e2)› have "x ∈ (fv e1 ∪ fv e2)" by simp
  hence "x ∈ fv e1 ∨ x ∈ fv e2" by auto
  thus ?case
  proof
    assume "x ∈ fv e1"
    from IH1[OF ‹Γ ⊢ e1 : T1› this ‹Γ x = Some High›] have "Γ ⊢ e1 : High" .
    with ‹Γ ⊢ e2 : T2› show ?thesis by(simp add:typeBinOp2)
  next 
    assume "x ∈ fv e2" 
    from IH2[OF ‹Γ ⊢ e2 : T2› this ‹Γ x = Some High›] have "Γ ⊢ e2 : High" .
    with ‹Γ ⊢ e1 : T1› show ?thesis by(simp add:typeBinOp3)
  qed
qed
lemma exprTypingLow: 
  assumes "Γ ⊢ e : Low" and "x ∈ fv e" shows "Γ x = Some Low"
using assms
proof (induct e)
  case (Val V)
  have "fv (Val V) =  {}" by (rule FVc)
  with ‹x ∈ fv (Val V)› have False by auto
  thus ?thesis by simp
next
  case (Var V)
  from ‹x ∈ fv (Var V)› have xV: "x = V" by simp
  from ‹Γ ⊢ Var V : Low› have "Γ V = Some Low" by (auto elim:secExprTyping.cases)
  with xV show ?thesis by simp
next
  case (BinOp e1 bop e2)
  note IH1 = ‹⟦Γ ⊢ e1 : Low; x ∈ fv e1⟧ ⟹ Γ x = Some Low›
  note IH2=‹⟦Γ ⊢ e2 : Low; x ∈ fv e2⟧ ⟹ Γ x = Some Low›
  from ‹Γ ⊢ e1 «bop» e2 : Low› have "Γ ⊢ e1 : Low" and "Γ ⊢ e2 : Low"
    by(auto elim:secExprTyping.cases)
  from ‹x ∈ fv (e1 «bop» e2)› have "x ∈ fv e1 ∪ fv e2" by (simp add:FVe)
  hence "x ∈ fv e1 ∨ x ∈ fv e2" by auto
  thus ?case
  proof
    assume "x ∈ fv e1"
    with IH1[OF ‹Γ ⊢ e1 : Low›] show ?thesis by auto
  next
    assume "x ∈ fv e2" 
    with IH2[OF ‹Γ ⊢ e2 : Low›] show ?thesis by auto
  qed
qed
lemma typeableFreevars:
  assumes "Γ ⊢ e : T" shows "fv e ⊆ dom Γ"
using assms
proof(induct e arbitrary:T)
  case (Val V)
  have "fv (Val V) = {}" by (rule FVc)
  thus ?case by simp
next
  case (Var V)
  show ?case
  proof
    fix x assume "x ∈ fv (Var V)"
    hence "x = V" by simp 
    from ‹Γ ⊢ Var V : T› have  "Γ V = Some T" by (auto elim:secExprTyping.cases)
    with ‹x = V› show "x ∈ dom Γ" by auto
  qed
next
  case (BinOp e1 bop e2)
  note IH1 = ‹⋀T. Γ ⊢ e1 : T  ⟹ fv e1 ⊆ dom Γ›
  note IH2 = ‹⋀T. Γ ⊢ e2 : T  ⟹ fv e2 ⊆ dom Γ›
  show ?case
  proof
    fix x assume "x ∈ fv (e1 «bop» e2)"
    from ‹Γ ⊢ e1 «bop» e2 : T› 
    have Q:"(∃T1. Γ ⊢ e1 : T1) ∧ (∃T2. Γ ⊢ e2 : T2)" 
      by(rule exprBinopTypeable)
    then obtain T1 where "Γ ⊢ e1 : T1" by blast
    from Q obtain T2 where "Γ ⊢ e2 : T2" by blast
    from IH1[OF ‹Γ ⊢ e1 : T1›] have "fv e1 ⊆ dom Γ" .
    moreover
    from IH2[OF ‹Γ ⊢ e2 : T2›] have "fv e2 ⊆ dom Γ" .
    ultimately have "(fv e1) ∪ (fv e2) ⊆ dom Γ" by auto
    hence "fv (e1 «bop» e2) ⊆ dom Γ" by(simp add:FVe)
    with ‹x ∈ fv (e1 «bop» e2)› show "x ∈ dom Γ" by auto
  qed
qed
lemma exprNotNone:
assumes "Γ ⊢ e : T" and "fv e ⊆ dom s"
shows "⟦e⟧ s ≠ None"
using assms
proof (induct e arbitrary: Γ T s)
  case (Val v)
  show ?case by(simp add:Val)
next
  case (Var V)
  have "⟦Var V⟧ s = s V" by (simp add:Var)
  have "V ∈ fv (Var V)" by (auto simp add:FVv)
  with ‹fv (Var V) ⊆ dom s› have "V ∈ dom s" by simp
  thus ?case by auto
next
  case (BinOp e1 bop e2)
  note IH1 = ‹⋀T. ⟦Γ ⊢ e1 : T; fv e1 ⊆ dom s ⟧  ⟹ ⟦e1⟧ s ≠ None›
  note IH2 = ‹⋀T. ⟦Γ ⊢ e2 : T; fv e2 ⊆ dom s ⟧  ⟹ ⟦e2⟧ s ≠ None›
  from ‹Γ ⊢ e1 «bop» e2 :  T› have "(∃T1. Γ ⊢ e1 : T1) ∧ (∃T2. Γ ⊢ e2 : T2)"
    by(rule exprBinopTypeable)
  then obtain T1 T2 where "Γ ⊢ e1 : T1" and "Γ ⊢ e2 : T2" by blast
  from ‹fv (e1 «bop» e2)  ⊆ dom s› have "fv e1 ∪ fv e2 ⊆ dom s" by(simp add:FVe)
  hence "fv e1 ⊆ dom s" and "fv e2 ⊆ dom s" by auto
  from IH1[OF ‹Γ ⊢ e1 : T1› ‹fv e1 ⊆ dom s›] have "⟦e1⟧s ≠ None" .
  moreover from IH2[OF ‹Γ ⊢ e2 : T2› ‹fv e2 ⊆ dom s›] have "⟦e2⟧s ≠ None" .
  ultimately show ?case
    apply(cases bop) apply auto
    apply(case_tac y,auto,case_tac ya,auto)+
    done
qed
subsection ‹Noninterference definitions›
subsubsection ‹Low Equivalence›
text ‹Low Equivalence is reflexive even if the involved states are undefined. 
  But in non-reflexive situations low variables must be initialized 
  (i.e. ‹∈ dom state›), otherwise the proof will not work. This is not 
  a restriction, but a natural requirement, and could be formalized as part of 
  a standard type system.
  Low equivalence is also symmetric and transitiv (see lemmas) hence an
  equivalence relation.›
definition lowEquiv :: "typeEnv ⇒ state ⇒ state ⇒ bool" (‹_ ⊢ _ ≈⇩L _›)
where "Γ ⊢ s1 ≈⇩L s2 ≡ ∀v∈dom Γ. Γ v = Some Low ⟶ (s1 v = s2 v)"
lemma lowEquivReflexive: "Γ ⊢ s1 ≈⇩L s1" 
by(simp add:lowEquiv_def)
lemma lowEquivSymmetric:
  "Γ ⊢ s1 ≈⇩L s2 ⟹ Γ ⊢ s2 ≈⇩L s1"
by(simp add:lowEquiv_def)
lemma lowEquivTransitive:
  "⟦Γ ⊢ s1 ≈⇩L s2; Γ ⊢ s2 ≈⇩L s3⟧ ⟹ Γ ⊢ s1 ≈⇩L s3"
by(simp add:lowEquiv_def)
subsubsection ‹Non Interference›
definition nonInterference :: "typeEnv ⇒ com ⇒ bool"
where "nonInterference Γ c ≡ 
  (∀s1 s2 s1' s2'. (Γ ⊢ s1 ≈⇩L s2 ∧ ⟨c,s1⟩ →* ⟨Skip,s1'⟩ ∧ ⟨c,s2⟩ →* ⟨Skip,s2'⟩) 
    ⟶ Γ ⊢ s1' ≈⇩L s2')"
lemma nonInterferenceI: 
  "⟦⋀s1 s2 s1' s2'. ⟦Γ ⊢ s1 ≈⇩L s2; ⟨c,s1⟩ →* ⟨Skip,s1'⟩; ⟨c,s2⟩ →* ⟨Skip,s2'⟩⟧
  ⟹ Γ ⊢ s1' ≈⇩L s2'⟧ ⟹ nonInterference Γ c"
by(auto simp:nonInterference_def)
lemma interpretLow:
  assumes "Γ ⊢ s1 ≈⇩L s2" and all:"∀V∈fv e. Γ V = Some Low"
  shows "⟦e⟧ s1 = ⟦e⟧ s2"
using all
proof (induct e)
  case (Val v)
  show ?case by (simp add: Val)
next
  case (Var V)
  have "⟦Var V⟧ s1 = s1 V" and "⟦Var V⟧ s2 = s2 V" by(auto simp:Var)
  have "V ∈ fv (Var V)" by(simp add:FVv)
  from ‹V ∈ fv (Var V)› ‹∀X∈fv (Var V). Γ X = Some Low› have "Γ V = Some Low" by simp
  with assms have "s1 V = s2 V" by(auto simp add:lowEquiv_def)
  thus ?case by auto
next
  case (BinOp e1 bop e2)
  note IH1 = ‹∀V∈fv e1. Γ V = Some Low ⟹ ⟦e1⟧s1 = ⟦e1⟧s2›
  note IH2 = ‹∀V∈fv e2. Γ V = Some Low ⟹ ⟦e2⟧s1 = ⟦e2⟧s2›
  from ‹∀V∈fv (e1 «bop» e2). Γ V = Some Low› have "∀V∈fv e1. Γ V = Some Low"
    and "∀V∈ fv e2. Γ V = Some Low" by auto
  from IH1[OF ‹∀V∈fv e1. Γ V = Some Low›] have "⟦e1⟧ s1 = ⟦e1⟧ s2" .
  moreover
  from IH2[OF ‹∀V∈fv e2. Γ V = Some Low›] have "⟦e2⟧ s1 = ⟦e2⟧ s2" .
  ultimately show ?case by(cases "⟦e1⟧ s2",auto)
qed
lemma interpretLow2:
  assumes "Γ ⊢ e : Low" and "Γ ⊢ s1 ≈⇩L s2" shows "⟦e⟧ s1 = ⟦e⟧ s2"
proof -
  from ‹Γ ⊢ e : Low› have "fv e ⊆ dom Γ" by(auto dest:typeableFreevars)
  have "∀x∈ fv e. Γ x = Some Low"
  proof
    fix x assume "x ∈ fv e"
    with ‹Γ ⊢ e : Low› show "Γ x = Some Low" by(auto intro:exprTypingLow)
  qed
  with ‹Γ ⊢ s1 ≈⇩L s2› show ?thesis by(rule interpretLow)
qed
lemma assignNIhighlemma:
  assumes "Γ ⊢ s1 ≈⇩L s2"  and "Γ V = Some High" and "s1' = s1(V:= ⟦e⟧ s1)" 
  and "s2' = s2(V:= ⟦e⟧ s2)"
  shows "Γ ⊢ s1' ≈⇩L s2'"
proof -
  { fix V' assume "V' ∈ dom Γ" and  "Γ V' = Some Low"
    from ‹Γ ⊢ s1 ≈⇩L s2›  ‹Γ V' = Some Low› have "s1 V' = s2 V'" 
      by(auto simp add:lowEquiv_def)
    have "s1' V' = s2' V'"
    proof(cases "V' = V")
      case True
      with ‹Γ V' = Some Low› ‹Γ V = Some High› have False by simp
      thus ?thesis by simp
    next
      case False
      with ‹s1' = s1(V:= ⟦e⟧ s1)› ‹s2' = s2(V:= ⟦e⟧ s2)›
      have "s1 V' = s1' V'" and "s2 V' = s2' V'" by auto
      with ‹s1 V' = s2 V'› show ?thesis by simp
    qed
  }
  thus ?thesis by(auto simp add:lowEquiv_def)
qed
lemma assignNIlowlemma:
  assumes "Γ ⊢ s1 ≈⇩L s2"  and "Γ V = Some Low" and "Γ ⊢ e : Low" 
  and "s1' = s1(V:= ⟦e⟧ s1)" and "s2' = s2(V:= ⟦e⟧ s2)"
  shows "Γ ⊢ s1' ≈⇩L s2'" 
proof -
  { fix V' assume "V' ∈ dom Γ" and  "Γ V' = Some Low"
    from ‹Γ ⊢ s1 ≈⇩L s2›  ‹Γ V' = Some Low›
    have "s1 V' = s2 V'" by(auto simp add:lowEquiv_def)
    have "s1' V' = s2' V'"
    proof(cases "V' = V")
      case True
      with ‹s1' = s1(V:= ⟦e⟧ s1)› ‹s2' = s2(V:= ⟦e⟧ s2)›
      have "s1' V' = ⟦e⟧ s1" and "s2' V' = ⟦e⟧ s2" by auto
      from ‹Γ ⊢ e : Low› ‹Γ ⊢ s1 ≈⇩L s2› have "⟦e⟧ s1 = ⟦e⟧ s2" 
        by(auto intro:interpretLow2)
      with ‹s1' V' = ⟦e⟧ s1› ‹s2' V' = ⟦e⟧ s2› show ?thesis by simp
    next
      case False
      with ‹s1' = s1(V:= ⟦e⟧ s1)› ‹s2' = s2(V:= ⟦e⟧ s2)›
      have "s1' V' = s1 V'" and "s2' V' = s2 V'" by auto
      with ‹s1 V' = s2 V'› have "s1' V' = s2' V'" by simp
      with False ‹s1' V' = s1 V'› ‹s2' V' = s2 V'›
      show ?thesis by auto
    qed
  }
  thus ?thesis by(simp add:lowEquiv_def)
qed
text ‹Sequential Compositionality is given the status of a theorem because 
  compositionality is no longer valid in case of concurrency›
theorem SeqCompositionality:
  assumes "nonInterference Γ c1" and "nonInterference Γ c2" 
  shows "nonInterference Γ (c1;;c2)"
proof(rule nonInterferenceI)
  fix s1 s2 s1' s2'
  assume "Γ ⊢ s1 ≈⇩L s2" and "⟨c1;;c2,s1⟩ →* ⟨Skip,s1'⟩" 
    and "⟨c1;;c2,s2⟩ →* ⟨Skip,s2'⟩"
  from ‹⟨c1;;c2,s1⟩ →* ⟨Skip,s1'⟩› obtain s1'' where "⟨c1,s1⟩ →* ⟨Skip,s1''⟩"
    and "⟨c2,s1''⟩ →* ⟨Skip,s1'⟩" by(auto dest:Seq_reds)
  from ‹⟨c1;;c2,s2⟩ →* ⟨Skip,s2'⟩› obtain s2'' where "⟨c1,s2⟩ →* ⟨Skip,s2''⟩"
    and "⟨c2,s2''⟩ →* ⟨Skip,s2'⟩" by(auto dest:Seq_reds)
  from ‹Γ ⊢ s1 ≈⇩L s2› ‹⟨c1,s1⟩ →* ⟨Skip,s1''⟩› ‹⟨c1,s2⟩ →* ⟨Skip,s2''⟩›
    ‹nonInterference Γ c1›
  have "Γ ⊢ s1'' ≈⇩L s2''" by(auto simp:nonInterference_def)
  with ‹⟨c2,s1''⟩ →* ⟨Skip,s1'⟩› ‹⟨c2,s2''⟩ →* ⟨Skip,s2'⟩› ‹nonInterference Γ c2› 
  show "Γ ⊢ s1' ≈⇩L s2'" by(auto simp:nonInterference_def)
qed
lemma WhileStepInduct:
  assumes while:"⟨while (b) c,s1⟩ →* ⟨Skip,s2⟩"
  and body:"⋀s1 s2. ⟨c,s1⟩ →* ⟨Skip,s2⟩  ⟹ Γ ⊢ s1 ≈⇩L s2" and "Γ,High ⊢ c"
  shows "Γ ⊢ s1 ≈⇩L s2"
using while
proof (induct rule:while_reds_induct)
  case (false s) thus ?case by(auto simp add:lowEquiv_def)
next 
  case (true s1 s3)
  from body[OF ‹⟨c,s1⟩ →* ⟨Skip,s3⟩›] have "Γ ⊢ s1 ≈⇩L s3" by simp
  with ‹Γ ⊢ s3 ≈⇩L s2› show ?case by(auto intro:lowEquivTransitive)
qed
text ‹In case control conditions from if/while are high, the body of an
  if/while must not change low variables in order to prevent implicit flow.
  That is, start and end state of any if/while body must be low equivalent.›
theorem highBodies:
  assumes "Γ,High ⊢ c" and "⟨c,s1⟩ →* ⟨Skip,s2⟩"
  shows "Γ ⊢ s1 ≈⇩L s2"
  
using assms
proof(induct c arbitrary:s1 s2 rule:com.induct)
  case Skip
  from ‹⟨Skip,s1⟩ →* ⟨Skip,s2⟩› have "s1 = s2" by (auto dest:Skip_reds)
  thus ?case by(simp add:lowEquiv_def)
next
  case (LAss V e)
  from ‹Γ,High ⊢ V:=e› have "Γ V = Some High" by(auto elim:secComTyping.cases)
  from ‹⟨V:=e,s1⟩ →* ⟨Skip,s2⟩› have "s2 = s1(V:= ⟦e⟧s1)" by (auto intro:LAss_reds)
  { fix V' assume "V' ∈ dom Γ" and "Γ V' = Some Low"
    have "s1 V' = s2 V'"
    proof(cases "V' = V")
      case True
      with ‹Γ V' = Some Low› ‹Γ V = Some High› have False by simp
      thus ?thesis by simp
    next
      case False
      with ‹s2 = s1(V:= ⟦e⟧s1)› show ?thesis by simp 
    qed
  }
  thus ?case by(auto simp add:lowEquiv_def)
next
  case (Seq c1 c2)
  note IH1 = ‹⋀s1 s2. ⟦Γ,High ⊢ c1; ⟨c1,s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2›
  note IH2 = ‹⋀s1 s2. ⟦Γ,High ⊢ c2; ⟨c2,s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2›
  from ‹Γ,High ⊢ c1;;c2› have "Γ,High ⊢ c1" and "Γ,High ⊢ c2"
    by(auto elim:secComTyping.cases)
  from ‹⟨c1;;c2,s1⟩ →* ⟨Skip,s2⟩› 
  have "∃s3. ⟨c1,s1⟩ →* ⟨Skip,s3⟩ ∧ ⟨c2,s3⟩ →* ⟨Skip,s2⟩" by(auto intro:Seq_reds)
  then obtain s3 where "⟨c1,s1⟩ →* ⟨Skip,s3⟩" and "⟨c2,s3⟩ →* ⟨Skip,s2⟩" by auto
  from IH1[OF ‹Γ,High ⊢ c1› ‹⟨c1,s1⟩ →* ⟨Skip,s3⟩›]
  have "Γ ⊢ s1 ≈⇩L s3" by simp
  from IH2[OF ‹Γ,High ⊢ c2› ‹⟨c2,s3⟩ →* ⟨Skip,s2⟩›]
  have "Γ ⊢ s3 ≈⇩L s2" by simp
  from ‹Γ ⊢ s1 ≈⇩L s3› ‹Γ ⊢ s3 ≈⇩L s2› show ?case
    by(auto intro:lowEquivTransitive)
next
  case (Cond b c1 c2)
  note IH1 = ‹⋀s1 s2. ⟦Γ,High ⊢ c1; ⟨c1,s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2›
  note IH2 = ‹⋀s1 s2. ⟦Γ,High ⊢ c2; ⟨c2,s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2›
  from ‹Γ,High ⊢ if (b) c1 else c2› have "Γ,High ⊢ c1" and "Γ,High ⊢ c2"
    by(auto elim:secComTyping.cases)
  from ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s2⟩› 
  have "⟦b⟧ s1 = Some true ∨ ⟦b⟧ s1 = Some false" by(auto dest:Cond_True_or_False)
  thus ?case
  proof
    assume "⟦b⟧ s1 = Some true"
    with ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s2⟩› have "⟨c1,s1⟩ →* ⟨Skip,s2⟩"
      by (auto intro:CondTrue_reds)
    from IH1[OF ‹Γ,High ⊢ c1› this] show ?thesis .
  next
    assume "⟦b⟧ s1 = Some false"
    with ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s2⟩› have "⟨c2,s1⟩ →* ⟨Skip,s2⟩"
      by(auto intro:CondFalse_reds)
    from IH2[OF ‹Γ,High ⊢ c2› this] show ?thesis .
  qed
next
  case (While b c')
  note IH = ‹⋀s1 s2. ⟦Γ,High ⊢ c'; ⟨c',s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2›
  from ‹Γ,High ⊢ while (b) c'› have "Γ,High ⊢ c'" by(auto elim:secComTyping.cases)
  from IH[OF this] 
  have "⋀s1 s2. ⟦⟨c',s1⟩ →* ⟨Skip,s2⟩⟧ ⟹ Γ ⊢ s1 ≈⇩L s2" .
  with ‹⟨while (b) c',s1⟩ →* ⟨Skip,s2⟩› ‹Γ,High ⊢ c'› 
  show ?case by(auto dest:WhileStepInduct)
qed
lemma CondHighCompositionality:
  assumes "Γ,High ⊢ if (b) c1 else c2"
  shows "nonInterference Γ (if (b) c1 else c2)"
proof(rule nonInterferenceI)
  fix s1 s2 s1' s2'
  assume "Γ ⊢ s1 ≈⇩L s2" and "⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩" 
    and "⟨if (b) c1 else c2,s2⟩ →* ⟨Skip,s2'⟩"
  show "Γ ⊢ s1' ≈⇩L s2'"
  proof -
    from ‹Γ,High ⊢ if (b) c1 else c2› ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩›
    have "Γ ⊢ s1 ≈⇩L s1'" by(auto dest:highBodies)
    from ‹Γ,High ⊢ if (b) c1 else c2› ‹⟨if (b) c1 else c2,s2⟩ →* ⟨Skip,s2'⟩›
    have "Γ ⊢ s2 ≈⇩L s2'" by(auto dest:highBodies)
    with ‹Γ ⊢ s1 ≈⇩L s2› have "Γ ⊢ s1 ≈⇩L s2'" by(auto intro:lowEquivTransitive)
    from ‹Γ ⊢ s1 ≈⇩L s1'› have "Γ ⊢ s1' ≈⇩L s1" by(auto intro:lowEquivSymmetric)
    with ‹Γ ⊢ s1 ≈⇩L s2'› show ?thesis by(auto intro:lowEquivTransitive)
  qed
qed
lemma CondLowCompositionality:
  assumes "nonInterference Γ c1" and "nonInterference Γ c2" and "Γ ⊢ b : Low" 
  shows "nonInterference Γ (if (b) c1 else c2)"
proof(rule nonInterferenceI)
  fix s1 s2 s1' s2'
  assume "Γ ⊢ s1 ≈⇩L s2" and "⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩" 
    and "⟨if (b) c1 else c2,s2⟩ →* ⟨Skip,s2'⟩"
  from ‹Γ ⊢ b : Low› ‹Γ ⊢ s1 ≈⇩L s2› have "⟦b⟧ s1 = ⟦b⟧ s2"
    by(auto intro:interpretLow2)
  from ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩› 
  have "⟦b⟧ s1 = Some true ∨ ⟦b⟧ s1 = Some false" by(auto dest:Cond_True_or_False)
  thus "Γ ⊢ s1' ≈⇩L s2'"
  proof
    assume "⟦b⟧ s1 = Some true"
    with ‹⟦b⟧ s1 = ⟦b⟧ s2› have "⟦b⟧ s2 = Some true" by(auto intro:CondTrue_reds)
    from ‹⟦b⟧ s1 = Some true› ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩›
    have "⟨c1,s1⟩ →* ⟨Skip,s1'⟩" by(auto intro:CondTrue_reds)
    from ‹⟦b⟧ s2 = Some true› ‹⟨if (b) c1 else c2,s2⟩ →* ⟨Skip,s2'⟩›
    have "⟨c1,s2⟩ →* ⟨Skip,s2'⟩" by(auto intro:CondTrue_reds)
    with ‹⟨c1,s1⟩ →* ⟨Skip,s1'⟩› ‹Γ ⊢ s1 ≈⇩L s2› ‹nonInterference Γ c1›
    show ?thesis by(auto simp:nonInterference_def)
  next
    assume "⟦b⟧ s1 = Some false"
    with ‹⟦b⟧ s1 = ⟦b⟧ s2› have "⟦b⟧ s2 = Some false" by(auto intro:CondTrue_reds)
    from ‹⟦b⟧ s1 = Some false› ‹⟨if (b) c1 else c2,s1⟩ →* ⟨Skip,s1'⟩›
    have "⟨c2,s1⟩ →* ⟨Skip,s1'⟩" by(auto intro:CondFalse_reds)
    from ‹⟦b⟧ s2 = Some false› ‹⟨if (b) c1 else c2,s2⟩ →* ⟨Skip,s2'⟩›
    have "⟨c2,s2⟩ →* ⟨Skip,s2'⟩" by(auto intro:CondFalse_reds)
    with ‹⟨c2,s1⟩ →* ⟨Skip,s1'⟩› ‹Γ ⊢ s1 ≈⇩L s2› ‹nonInterference Γ c2›
    show ?thesis by(auto simp:nonInterference_def)
  qed
qed
lemma WhileHighCompositionality:
  assumes "Γ,High ⊢ while (b) c'"
  shows "nonInterference Γ (while (b) c')"
proof(rule nonInterferenceI)
  fix s1 s2 s1' s2'
  assume "Γ ⊢ s1 ≈⇩L s2" and "⟨while (b) c',s1⟩ →* ⟨Skip,s1'⟩"
    and "⟨while (b) c',s2⟩ →* ⟨Skip,s2'⟩"
  show "Γ ⊢ s1' ≈⇩L s2'"
  proof -
    from ‹Γ,High ⊢ while (b) c'› ‹⟨while (b) c',s1⟩ →* ⟨Skip,s1'⟩›
    have "Γ ⊢ s1 ≈⇩L s1'" by(auto dest:highBodies)
    from ‹Γ,High ⊢ while (b) c'› ‹⟨while (b) c',s2⟩ →* ⟨Skip,s2'⟩›
    have "Γ ⊢ s2 ≈⇩L s2'" by(auto dest:highBodies)
    with ‹Γ ⊢ s1 ≈⇩L s2› have "Γ ⊢ s1 ≈⇩L s2'" by(auto intro:lowEquivTransitive)
    from ‹Γ ⊢ s1 ≈⇩L s1'› have "Γ ⊢ s1' ≈⇩L s1" by(auto intro:lowEquivSymmetric)
    with ‹Γ ⊢ s1 ≈⇩L s2'› show ?thesis by(auto intro:lowEquivTransitive)
  qed
qed
lemma WhileLowStepInduct:
  assumes  while1: "⟨while (b) c',s1⟩ →* ⟨Skip,s1'⟩"   
  and      while2: "⟨while (b) c',s2⟩→*⟨Skip,s2'⟩" 
  and      "Γ ⊢ b : Low"
  and      body:"⋀s1 s1' s2 s2'. ⟦⟨c',s1⟩ →* ⟨Skip,s1'⟩; ⟨c',s2⟩ →* ⟨Skip,s2'⟩;
                                   Γ ⊢ s1 ≈⇩L s2⟧  ⟹  Γ ⊢ s1' ≈⇩L s2'"
  and      le: "Γ ⊢ s1 ≈⇩L s2"
  shows    "Γ ⊢ s1' ≈⇩L s2'"
using while1 le while2
proof (induct arbitrary:s2 rule:while_reds_induct)
  case (false s1)
  from ‹Γ ⊢ b : Low› ‹Γ ⊢ s1 ≈⇩L s2› have "⟦b⟧ s1 = ⟦b⟧ s2" by(auto intro:interpretLow2)
  with ‹⟦b⟧ s1 = Some false› have "⟦b⟧ s2 = Some false" by simp
  with ‹⟨while (b) c',s2⟩→*⟨Skip,s2'⟩› have "s2 = s2'" by(auto intro:WhileFalse_reds)
  with ‹Γ ⊢ s1 ≈⇩L s2› show ?case by auto
next 
  case (true s1 s1'')
  note IH = ‹⋀s2''. ⟦Γ ⊢ s1'' ≈⇩L s2''; ⟨while (b) c',s2''⟩ →* ⟨Skip,s2'⟩⟧ 
    ⟹ Γ ⊢ s1' ≈⇩L s2'›
  from ‹Γ ⊢ b : Low› ‹Γ ⊢ s1 ≈⇩L s2› have "⟦b⟧ s1 = ⟦b⟧ s2" by(auto intro:interpretLow2)
  with ‹⟦b⟧ s1 = Some true› have "⟦b⟧ s2 = Some true" by simp
  with ‹⟨while (b) c',s2⟩ →* ⟨Skip,s2'⟩› obtain s2'' where "⟨c',s2⟩ →* ⟨Skip,s2''⟩"
    and "⟨while (b) c',s2''⟩ →* ⟨Skip,s2'⟩" by(auto dest:WhileTrue_reds)
  from body[OF ‹⟨c',s1⟩ →* ⟨Skip,s1''⟩› ‹⟨c',s2⟩ →* ⟨Skip,s2''⟩› ‹Γ ⊢ s1 ≈⇩L s2›]
  have "Γ ⊢ s1'' ≈⇩L s2''" .
  from IH[OF this ‹⟨while (b) c',s2''⟩ →* ⟨Skip,s2'⟩›] show ?case .
qed
lemma WhileLowCompositionality:
  assumes "nonInterference Γ c'" and "Γ ⊢ b : Low" and "Γ,Low ⊢ c'"
  shows "nonInterference Γ (while (b) c')"
proof(rule nonInterferenceI)
  fix s1 s2 s1' s2'
  assume "Γ ⊢ s1 ≈⇩L s2" and "⟨while (b) c',s1⟩ →* ⟨Skip,s1'⟩" 
    and "⟨while (b) c',s2⟩ →* ⟨Skip,s2'⟩"
  { fix s1 s2 s1'' s2''
    assume "⟨c',s1⟩ →* ⟨Skip,s1''⟩" and "⟨c',s2⟩ →* ⟨Skip,s2''⟩" 
      and  "Γ ⊢ s1 ≈⇩L s2"  
    with ‹nonInterference Γ c'› have "Γ ⊢ s1'' ≈⇩L s2''"
      by(auto simp:nonInterference_def)
  }
  hence "⋀s1 s1'' s2 s2''. ⟦⟨c',s1⟩ →* ⟨Skip,s1''⟩; ⟨c',s2⟩ →* ⟨Skip,s2''⟩;
                             Γ ⊢ s1 ≈⇩L s2⟧  ⟹  Γ ⊢ s1'' ≈⇩L s2''" by auto
  with ‹⟨while (b) c',s1⟩ →* ⟨Skip,s1'⟩› ‹⟨while (b) c',s2⟩ →* ⟨Skip,s2'⟩›
    ‹Γ ⊢ b : Low› ‹Γ ⊢ s1 ≈⇩L s2› show "Γ ⊢ s1' ≈⇩L s2'"
    by(auto intro:WhileLowStepInduct)
qed
text ‹and now: the main theorem:›
theorem secTypeImpliesNonInterference:
  "Γ,T ⊢ c ⟹ nonInterference Γ c"
proof (induct c arbitrary:T rule:com.induct)
  case Skip
  show ?case
  proof(rule nonInterferenceI)
    fix s1 s2 s1' s2'
    assume "Γ ⊢ s1 ≈⇩L s2" and "⟨Skip,s1⟩ →* ⟨Skip,s1'⟩" and "⟨Skip,s2⟩ →* ⟨Skip,s2'⟩"
    from ‹⟨Skip,s1⟩ →* ⟨Skip,s1'⟩› have "s1 = s1'" by(auto dest:Skip_reds)
    from ‹⟨Skip,s2⟩ →* ⟨Skip,s2'⟩› have "s2 = s2'" by(auto dest:Skip_reds)
    from ‹Γ ⊢ s1 ≈⇩L s2› and ‹s1 = s1'› and ‹s2 = s2'›
    show "Γ ⊢ s1' ≈⇩L s2'" by simp
  qed
next
  case (LAss V e)
  from ‹Γ,T ⊢ V:=e› 
  have varprem:"(Γ V = Some High) ∨ (Γ V = Some Low ∧ Γ ⊢ e : Low ∧ T = Low)"
    by (auto elim:secComTyping.cases)
  show ?case
  proof(rule nonInterferenceI)
    fix s1 s2 s1' s2'
    assume "Γ ⊢ s1 ≈⇩L s2" and "⟨V:=e,s1⟩ →* ⟨Skip,s1'⟩" and "⟨V:=e,s2⟩ →* ⟨Skip,s2'⟩"
    from ‹⟨V:=e,s1⟩ →* ⟨Skip,s1'⟩› have "s1' = s1(V:=⟦e⟧ s1)" by(auto intro:LAss_reds)
    from ‹⟨V:=e,s2⟩ →* ⟨Skip,s2'⟩› have "s2' = s2(V:=⟦e⟧ s2)" by(auto intro:LAss_reds)
    from varprem show "Γ ⊢ s1' ≈⇩L s2'"
    proof
      assume "Γ V = Some High"
      with ‹Γ ⊢ s1 ≈⇩L s2› ‹s1' = s1(V:=⟦e⟧ s1)› ‹s2' = s2(V:=⟦e⟧ s2)›
      show ?thesis by(auto intro:assignNIhighlemma)
    next
      assume "Γ V = Some Low ∧ Γ ⊢ e : Low ∧ T = Low"
      with ‹Γ ⊢ s1 ≈⇩L s2› ‹s1' = s1(V:=⟦e⟧ s1)› ‹s2' = s2(V:=⟦e⟧ s2)›
      show ?thesis by(auto intro:assignNIlowlemma)
    qed
  qed
next
  case (Seq c1 c2)
  note IH1 = ‹⋀T. Γ,T ⊢ c1 ⟹ nonInterference Γ c1›
  note IH2 = ‹⋀T. Γ,T ⊢ c2 ⟹ nonInterference Γ c2›
  show ?case
  proof (cases T)
    case High
    with ‹Γ,T ⊢ c1;;c2› have "Γ,High ⊢ c1" and "Γ,High ⊢ c2"
      by(auto elim:secComTyping.cases)
    from IH1[OF ‹Γ,High ⊢ c1›] have "nonInterference Γ c1" .
    moreover
    from IH2[OF ‹Γ,High ⊢ c2›] have "nonInterference Γ c2" .
    ultimately show ?thesis by (auto intro:SeqCompositionality)
  next
    case Low
    with ‹Γ,T ⊢ c1;;c2›
    have "(Γ,Low ⊢ c1 ∧ Γ,Low ⊢ c2) ∨ Γ,High ⊢ c1;;c2"
      by(auto elim:secComTyping.cases)
    thus ?thesis 
    proof
      assume "Γ,Low ⊢ c1 ∧ Γ,Low ⊢ c2"
      hence "Γ,Low ⊢ c1" and "Γ,Low ⊢ c2" by simp_all
      from IH1[OF ‹Γ,Low ⊢ c1›] have "nonInterference Γ c1" .
      moreover
      from IH2[OF ‹Γ,Low ⊢ c2›] have "nonInterference Γ c2" .
      ultimately show ?thesis by(auto intro:SeqCompositionality)
    next
      assume "Γ,High ⊢ c1;;c2"
      hence "Γ,High ⊢ c1" and "Γ,High ⊢ c2" by(auto elim:secComTyping.cases)
      from IH1[OF ‹Γ,High ⊢ c1›] have "nonInterference Γ c1" .
      moreover
      from IH2[OF ‹Γ,High ⊢ c2›] have "nonInterference Γ c2" .
      ultimately show ?thesis by(auto intro:SeqCompositionality)
    qed
  qed
next
  case (Cond b c1 c2)
  note IH1 = ‹⋀T. Γ,T ⊢ c1 ⟹ nonInterference Γ c1›
  note IH2 = ‹⋀T. Γ,T ⊢ c2 ⟹ nonInterference Γ c2›
  show ?case
  proof (cases T)
    case High
    with ‹Γ,T ⊢ if (b) c1 else c2› show ?thesis
      by(auto intro:CondHighCompositionality)
  next
    case Low
    with ‹Γ,T ⊢ if (b) c1 else c2› 
    have "(Γ ⊢ b : Low ∧ Γ,Low ⊢ c1 ∧Γ,Low ⊢ c2) ∨ Γ,High ⊢ if (b) c1 else c2"
      by(auto elim:secComTyping.cases)
    thus ?thesis
    proof
      assume "Γ ⊢ b : Low ∧ Γ,Low ⊢ c1 ∧ Γ,Low ⊢ c2"
      hence "Γ ⊢ b : Low" and "Γ,Low ⊢ c1" and "Γ,Low ⊢ c2" by simp_all
      from IH1[OF ‹Γ,Low ⊢ c1›] have "nonInterference Γ c1" .
      moreover
      from IH2[OF ‹Γ,Low ⊢ c2›] have "nonInterference Γ c2" .
      ultimately show ?thesis using ‹Γ ⊢ b : Low›
        by(auto intro:CondLowCompositionality)
    next
      assume "Γ,High ⊢ if (b) c1 else c2"
      thus ?thesis by(auto intro:CondHighCompositionality)
    qed
  qed
next
  case (While b c')
  note IH = ‹⋀T. Γ,T ⊢ c' ⟹ nonInterference Γ c'›
  show ?case
  proof(cases T)
    case High
    with ‹Γ,T ⊢ while (b) c'› show ?thesis by(auto intro:WhileHighCompositionality)
  next
    case Low
    with ‹Γ,T ⊢ while (b) c'› 
    have "(Γ ⊢ b : Low ∧ Γ,Low ⊢ c') ∨ Γ,High ⊢ while (b) c'"
      by(auto elim:secComTyping.cases)
    thus ?thesis
    proof
      assume "Γ ⊢ b : Low ∧ Γ,Low ⊢ c'"
      hence "Γ ⊢ b : Low" and "Γ,Low ⊢ c'" by simp_all
      moreover
      from IH[OF ‹Γ,Low ⊢ c'›] have "nonInterference Γ c'" .
      ultimately show ?thesis by(auto intro:WhileLowCompositionality)
    next
      assume "Γ,High ⊢ while (b) c'"
      thus ?thesis by(auto intro:WhileHighCompositionality)
    qed
  qed
qed
end