Theory Fun1_insecure

subsection "Proof"
theory Fun1_insecure
imports Fun1
begin


subsubsection "Concrete leak"

definition "PC  {0..6}"

definition "same_xx cfg3 cfgs3 cfg4 cfgs4  
 vstore (getVstore (stateOf cfg3)) xx = vstore (getVstore (stateOf cfg4)) xx 
 (cfg3'set cfgs3. vstore (getVstore (stateOf cfg3')) xx = vstore (getVstore (stateOf cfg3)) xx)  
 (cfg4'set cfgs4. vstore (getVstore (stateOf cfg4')) xx = vstore (getVstore (stateOf cfg4)) xx)"

(* two possible program traces for normal execution*)
definition "trueProg = {2,3,4,5,6}"
definition "falseProg = {2,3,5,6}"


(*pstate *)
definition "pstate1  update pstate0 [3]"
definition "pstate2  update pstate1 [5,5]"

lemmas pstate_def = pstate1_def pstate2_def

(*heap*)
(*provide different memories*)
fun hh3:: "nat  int" where 
"hh3 x =  (if x = (nat NN + 1) then 5 else 0)"

definition "h3 (Heap hh3)"

fun hh4:: "nat  int" where 
"hh4 x = (if x = (nat NN + 1) then 6 else 0)"

definition "h4 (Heap hh4)"

lemmas h_def = h3_def h4_def hh3.simps hh4.simps

(*used to show difference in heap vals*)
lemma ss_neq_aux1:"nat(5 * 512)  nat (6 * 512)" by auto
lemma ss_neq_aux2:"nat(3 * 512)  nat (5 * 512)" by auto
lemmas ss_neq = ss_neq_aux1 ss_neq_aux2
(*pointer*)
definition "p  nat size_aa1 + nat size_aa2"

(*vstore and reads*)

definition "vs1  (vs0(xx := NN + 1))"


definition "vs2  (vs1(tt := 0))"

definition "aa1i  array_loc aa1 (nat (vs2 xx)) avst'"

(*divergence between 3 and 4*)

definition "aa2vs3  array_loc aa2 (nat (hh3 aa1i * 512)) avst'"

definition "vs33 = vs2(tt := hh3 aa2vs3)"

(**)
definition "aa2vs4  array_loc aa2 (nat (hh4 aa1i * 512)) avst'"

definition "vs34 = vs2(tt := hh4 aa2vs4)"

lemmas readsm_def = aa1i_def aa2vs3_def aa2vs4_def
lemmas vs_def = vs0.simps vs1_def vs2_def vs33_def vs34_def


(*states*)
definition "s03  (State (Vstore vs0) avst' h3 p)"
definition "s13  (State (Vstore vs1) avst' h3 p)"
definition "s23  (State (Vstore vs2) avst' h3 p)"
definition "s33  (State (Vstore vs33) avst' h3 p)"

definition "s04  (State (Vstore vs0) avst' h4 p)"
definition "s14  (State (Vstore vs1) avst' h4 p)"
definition "s24  (State (Vstore vs2) avst' h4 p)"
definition "s34  (State (Vstore vs34) avst' h4 p)"

lemmas s_def = s03_def s13_def s23_def s33_def 
               s04_def s14_def s24_def s34_def

(*s3 stateA's*)
definition "(s30:: stateO)  (pstate0, (Config 0 s03), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s31:: stateO)  (pstate0, (Config 1 s03), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s32:: stateO)  (pstate0, (Config 2 s13), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s33:: stateO)  (pstate0, (Config 3 s23), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s34:: stateO)  (pstate1, (Config 5 s23), [Config 4 s23], repeat (NN+1), repeat (NN+1), {})"
definition "(s35:: stateO)  (pstate1, (Config 5 s23), [Config 5 s33], repeat (NN+1), repeat (NN+1), {aa2vs3, aa1i})"
definition "(s36:: stateO)  (pstate2, (Config 5 s23), [], repeat (NN+1), repeat (NN+1), {aa2vs3, aa1i})"
definition "(s37:: stateO)  (pstate2, (Config 6 s23), [], repeat (NN+1), repeat (NN+1), {aa2vs3, aa1i})"

lemmas s3_def = s30_def s31_def s32_def s33_def s34_def s35_def s36_def s37_def

lemmas state_def = s_def h_def vs_def readsm_def pstate_def avst_defs


(*s3 transition list*)
definition "s3_trans  [s30, s31, s32, s33, s34, s35, s36, s37]"
lemmas s3_trans_defs = s3_trans_def s3_def 

lemma hd_s3_trans[simp]: "hd s3_trans = s30" by (simp add: s3_trans_def)
lemma s3_trans_nemp[simp]: "s3_trans  []" by (simp add: s3_trans_def)


(*transitions*)
lemma s301[simp]:"s30 →S s31"
  unfolding s3_def
  using nonspec_normal
  by simp

lemma s312[simp]:"s31 →S s32"
  unfolding s3_def state_def
  using nonspec_normal
  by simp

lemma s323[simp]:"s32 →S s33"
  unfolding s3_def state_def
  by (simp add: finalM_iff)

lemma s334[simp]:"s33 →S s34"
  unfolding s3_def state_def
  using nonspec_mispred
  by (simp add: finalM_iff)

lemma s345[simp]:"s34 →S s35"
  unfolding s3_def state_def
  using spec_normal
  by (simp_all add: finalM_iff, blast) 

lemma s356[simp]:"s35 →S s36"
  unfolding s3_def state_def
  using spec_resolve
  by simp

lemma s367[simp]:"s36 →S s37"
  unfolding s3_def state_def
  using nonspec_normal
  by simp

lemma finalS_s37[simp]:"finalS s37"
  unfolding finalS_def final_def s3_def
  by (simp add: stepS_endPC)

lemmas s3_trans_simps = s301 s312 s323 s334 s345 s356 s367

(*s4 stateA's*)
definition "(s40:: stateO)  (pstate0, (Config 0 s04), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s41:: stateO)  (pstate0, (Config 1 s04), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s42:: stateO)  (pstate0, (Config 2 s14), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s43:: stateO)  (pstate0, (Config 3 s24), [], repeat (NN+1), repeat (NN+1), {})"
definition "(s44:: stateO)  (pstate1, (Config 5 s24), [Config 4 s24], repeat (NN+1), repeat (NN+1), {})"
definition "(s45:: stateO)  (pstate1, (Config 5 s24), [Config 5 s34], repeat (NN+1), repeat (NN+1), {aa2vs4, aa1i})"
definition "(s46:: stateO)  (pstate2, (Config 5 s24), [], repeat (NN+1), repeat (NN+1), {aa2vs4, aa1i})"
definition "(s47:: stateO)  (pstate2, (Config 6 s24), [], repeat (NN+1), repeat (NN+1), {aa2vs4, aa1i})"

lemmas s4_def = s40_def s41_def s42_def s43_def s44_def s45_def s46_def s47_def


(*s4 transition list*)
definition "s4_trans  [s40, s41, s42, s43, s44, s45, s46, s47]"
lemmas s4_trans_defs = s4_trans_def s4_def

lemma hd_s4_trans[simp]: "hd s4_trans = s40" by (simp add: s4_trans_def)
lemma s4_trans_nemp[simp]: "s4_trans  []" by (simp add: s4_trans_def)


(*transitions*)
lemma s401[simp]:"s40 →S s41"
  unfolding s4_def
  using nonspec_normal
  by simp

lemma s412[simp]:"s41 →S s42"
  unfolding s4_def state_def
  using nonspec_normal
  by simp

lemma s424[simp]:"s42 →S s43"
  unfolding s4_def state_def
  using nonspec_normal
  by (simp add: finalM_iff)

lemma s434[simp]:"s43 →S s44"
  unfolding s4_def state_def
  using nonspec_mispred
  by (simp add: finalM_iff)

lemma s445[simp]:"s44 →S s45"
  unfolding s4_def state_def
  using spec_normal 
  by (simp add: finalM_iff, blast)

lemma s456[simp]:"s45 →S s46"
  unfolding s4_def state_def
  using spec_resolve
  by simp

lemma s467[simp]:"s46 →S s47"
  unfolding s4_def state_def
  using nonspec_normal
  by simp

lemma finalS_s47[simp]:"finalS s47"
  unfolding finalS_def final_def s4_def
  by (simp add: stepS_endPC)


lemmas s4_trans_simps = s401 s412 s424 s434 s445 s456 s467



subsubsection "Auxillary lemmas for disproof"
lemma validS_s3_trans[simp]:"Opt.validS s3_trans"
  unfolding Opt.validS_def validTransO.simps s3_trans_def
  apply safe  
  subgoal for i using cases_5[of i] 
    by(elim disjE, simp_all) .


lemma validS_s4_trans[simp]:"Opt.validS s4_trans"
  unfolding Opt.validS_def validTransO.simps s4_trans_def
  apply safe
  subgoal for i using cases_5[of i] 
  by(elim disjE, simp_all) .


lemma finalS_s3[simp]:"finalS (last s3_trans)" by (simp add: s3_trans_def)
lemma finalS_s4[simp]:"finalS (last s4_trans)" by (simp add: s4_trans_def)

lemma filter_s3[simp]:"(filter isIntO (butlast s3_trans)) = (butlast s3_trans)"
  unfolding s3_trans_def finalS_def final_def
  using s3_trans_simps validTransO.simps validTransO_iff_nextS 
  by (smt (verit) butlast.simps(2) filter.simps(1,2) isIntO.elims(3))

lemma filter_s4[simp]:"(filter isIntO (butlast s4_trans)) = (butlast s4_trans)"
  unfolding s4_trans_def finalS_def final_def
  using s4_trans_simps validTransO.simps validTransO_iff_nextS 
  by (smt (verit) butlast.simps(2) filter.simps(1,2) isIntO.elims(3))

lemma S_s3_trans[simp]:"Opt.S s3_trans = [s03]"
  apply (simp add: Opt.S_def filtermap_def)
  unfolding s3_trans_defs by simp

lemma S_s4_trans[simp]:"Opt.S s4_trans = [s04]"
  apply (simp add: Opt.S_def filtermap_def)
  unfolding s4_trans_defs by simp


lemma finalB_noStep[simp]:"s1'. finalB (cfg1, ibT1, ibUT1)  (cfg1, ibT1, ibUT1, ls1) →N s1'  False"
  unfolding finalN_def final_def finalB_eq_finalN by auto

subsubsection "Disproof of fun1"
(*DISPROOF*)
fun common_memory::"config  config  bool" where 
"common_memory cfg1 cfg2 =
 (let h1 = (getHheap (stateOf cfg1)); 
      h2 = (getHheap (stateOf cfg2)) in
 ((xread_add. h1 x = h2 x  h1 x = 0) 
  (getAvstore (stateOf cfg1)) = avst' 
  (getAvstore (stateOf cfg2)) = avst'))"
(*for proof ease*)
lemma heap_eq0[simp]: "x. x  Suc NN  hh1' x = hh2' x  hh1' x = 0  hh2' NN = 0" 
  by (metis n_not_Suc_n)
lemma heap1_eq0[simp]:"x. x  Suc NN  hh1' x = hh2' x  hh1' x = 0 
               vs2 xx < NN 
               hh2' (nat (vs2 xx)) = 0"
  using le_less_Suc_eq nat_le_eq_zle nat_less_eq_zless 
  by (metis lessI nat_int order.asym)

fun Γ_inv::"stateV  state list  stateV  state list  bool" where
"Γ_inv (cfg1,ibT1,ibUT1,ls1) sl1 (cfg2,ibT2,ibUT2,ls2) sl2 = 
(
 (pcOf cfg1 = pcOf cfg2)  

 (pcOf cfg1 < 2  ibUT1  LNil  ibUT2  LNil)  

 (pcOf cfg1 > 2  same_var_val tt 0 cfg1 cfg2) 

 (pcOf cfg1 > 1  (same_var xx cfg1 cfg2) 

                    (vsi_t cfg1  pcOf cfg1  trueProg) 

                    (vsi_f cfg1  pcOf cfg1  falseProg))
 
 ls1 = ls2 

 pcOf cfg1  PC 
 common_memory cfg1 cfg2
)"

declare Γ_inv.simps[simp del]
lemmas Γ_def = Γ_inv.simps
lemmas Γ_defs = Γ_def common_memory.simps PC_def aa1i_def
                trueProg_def falseProg_def same_var_val_def same_var_def

lemma Γ_implies:"Γ_inv (cfg1,ibT1, ibUT1,ls1) sl1 (cfg2,ibT2,ibUT2,ls2) sl2  
  pcOf cfg1  6  pcOf cfg2  6  

  (pcOf cfg1 = 4  vsi_t cfg1) 
  (pcOf cfg2 = 4  vsi_t cfg2) 
  (pcOf cfg1 > 1  vsi_t cfg1  vsi_t cfg2) 

  (finalB (cfg1,ibT1,ibUT1)  pcOf cfg1 = 6) 
  (finalB (cfg2,ibT2,ibUT2)  pcOf cfg2 = 6)
"
  unfolding Γ_defs
  apply(elim conjE, intro conjI)
  subgoal using atLeastAtMost_iff by blast
  subgoal using vs_xx_cases[of cfg2] by (elim disjE, simp_all) 
  subgoal apply (rule impI,simp) using vs_xx_cases[of cfg1] by (elim disjE, simp_all)
  subgoal apply (rule impI,simp) using vs_xx_cases[of cfg2] vsi_defs by (elim disjE, simp_all)
  subgoal by (simp add: vsi_defs)
  using finalB_pcOf_iff 
   apply (metis atLeastAtMost_iff one_less_numeral_iff semiring_norm(76))
  using finalB_pcOf_iff
  by (metis atLeastAtMost_iff numeral_One numeral_less_iff semiring_norm(76))

(*istate*)
lemma istateO_s3[simp]:"istateO s30" unfolding s3_def state_def by simp
lemma istateO_s4[simp]:"istateO s40" unfolding s4_def state_def by simp

(*validFromS*)
lemma validFromS_s3[simp]:"Opt.validFromS s30 s3_trans"
  unfolding Opt.validFromS_def by simp

lemma validFromS_s4[simp]:"Opt.validFromS s40 s4_trans"
  unfolding Opt.validFromS_def by simp

(*completedFromO*)

lemma completedFromO_s3[simp]:"completedFromO s30 s3_trans"
  unfolding Opt.completedFrom_def by simp

lemma completedFromO_s4[simp]:"completedFromO s40 s4_trans"
  unfolding Opt.completedFrom_def by simp

(*Act eq*)
lemma Act_eq[simp]:"Opt.A s3_trans = Opt.A s4_trans"
  apply (simp add: Opt.A_def filtermap_def)
  unfolding s3_trans_defs s4_trans_defs
  by simp

lemma aa2_neq:"aa2vs3  aa2vs4"
  unfolding vs_def readsm_def avst_defs h_def array_loc_def  
  by (simp add: avst_defs array_base_def split: if_splits)

lemma aa1_neq:"aa2vs3  aa1i"
  apply(rule notI)
  unfolding vs_def readsm_def avst_defs h_def array_loc_def  
  by (simp add: avst_defs array_base_def split: if_splits)

lemma aa1_neq2:"aa2vs4  aa1i"
  apply(rule notI)
  unfolding vs_def readsm_def avst_defs h_def array_loc_def  
  by (simp add: avst_defs array_base_def split: if_splits)

(*Obs neq*)
lemma Obs_neq[simp]:"Opt.O s3_trans  Opt.O s4_trans"
  apply (simp add: Opt.O_def filtermap_def)
  unfolding s3_trans_def s4_trans_def apply clarsimp
  unfolding s3_trans_defs s4_trans_defs apply simp
  using aa2_neq aa1_neq aa1_neq2 by blast
   
  

lemma Γ_init[simp]:"s1 s2. istateV s1  corrState s1 s30  istateV s2  corrState s2 s40  Γ_inv s1 [s03] s2 [s04]"
  subgoal for s1 s2 apply(cases s1, cases s2, simp) 
    unfolding s3_def s4_def s_def h_def by (auto simp: Γ_defs) .

lemma val_neq_1:"nat (hh2' (nat (vs2 xx)) * 512)  1" 
  by (smt (z3) nat_less_eq_zless nat_one_as_int)


(*unwindSD*)
lemma unwindSD[simp]:"Rel_Sec.unwindSDCond validTransV istateV isSecV getSecV isIntV getIntV Γ_inv"
unfolding unwindSDCond_def
proof(intro allI, rule impI, elim conjE,intro conjI)
      fix ss1 ss2 sl1 sl2
      assume "reachV ss1" "reachV ss2" 
       and Γ:"Γ_inv ss1 sl1 ss2 sl2"

      obtain cfg1 ibT1 ibUT1 ls1 where ss1: "ss1 = (cfg1, ibT1, ibUT1, ls1)"
        by (cases ss1, auto) 
      obtain cfg2 ibT2 ibUT2 ls2 where ss2: "ss2 = (cfg2, ibT2, ibUT2, ls2)"
        by (cases ss2, auto) 
      note ss = ss1 ss2 

      obtain pc1 vs1 avst1 h1 p1 where 
        cfg1: "cfg1 = Config pc1 (State (Vstore vs1) avst1 h1 p1)"
        by (cases cfg1) (metis state.collapse vstore.collapse)
      obtain pc2 vs2 avst2 h2 p2 where 
        cfg2: "cfg2 = Config pc2 (State (Vstore vs2) avst2 h2 p2)"
        by (cases cfg2) (metis state.collapse vstore.collapse)
      note cfg = cfg1 cfg2

      obtain hh1 where h1: "h1 = Heap hh1" by(cases h1, auto)
      obtain hh2 where h2: "h2 = Heap hh2" by(cases h2, auto)
      note hh = h1 h2

      show "isIntV ss1 = isIntV ss2" 
        using  Γ unfolding isIntV.simps ss
        unfolding Γ_defs
        using vs_xx_cases[of cfg1]
        apply (elim disjE) by simp_all

      then have finalB:"finalB (cfg1, ibT1, ibUT1) = finalB (cfg2, ibT2, ibUT2)"
        unfolding isIntV.simps finalN_iff_finalB ss by blast

      show "¬ isIntV ss1  move1 Γ_inv ss1 sl1 ss2 sl2  move2 Γ_inv ss1 sl1 ss2 sl2"
        apply(unfold ss, auto)
        subgoal unfolding move1_def finalB_defs by auto
        subgoal unfolding finalB 
                unfolding move2_def finalB_defs by auto . 

      show "isIntV ss1  getActV ss1 = getActV ss2  getObsV ss1 = getObsV ss2  move12 Γ_inv ss1 sl1 ss2 sl2"
      proof(unfold ss isIntV.simps finalN_iff_finalB, intro impI, rule conjI)
        assume final:"¬ finalB (cfg1, ibT1, ibUT1)" and
              getAct:"getActV (cfg1, ibT1, ibUT1, ls1) = getActV (cfg2, ibT2, ibUT2, ls2)"
        have not6:"pc1 = 6  False"
          using cfg final Γ
          by simp

        show "getObsV (cfg1, ibT1, ibUT1, ls1) = getObsV (cfg2, ibT2, ibUT2, ls2)" 
          using Γ getAct unfolding ss 
          apply-apply(frule Γ_implies, elim conjE)
          using cases_5[of "pcOf cfg1"] cases_5[of "pcOf cfg2"] 
          by(elim disjE, simp_all add: Γ_defs final)

        show "move12 Γ_inv (cfg1, ibT1, ibUT1, ls1) sl1 (cfg2, ibT2, ibUT2, ls2) sl2" 
        unfolding move12_def validEtransO.simps 
      proof(intro allI, rule impI, elim conjE,unfold validTransV.simps isSecV_iff getSecV.simps fst_conv)
          fix ss1' ss2' sl1' sl2'

          assume v: "(cfg1, ibT1, ibUT1, ls1) →N ss1'" "(cfg2, ibT2, ibUT2, ls2) →N ss2'" and
               sec: "pcOf cfg1  0  sl1 = sl1'  pcOf cfg1 = 0  sl1 = stateOf cfg1 # sl1'"
                    "pcOf cfg2  0  sl2 = sl2'  pcOf cfg2 = 0  sl2 = stateOf cfg2 # sl2'"
          
          obtain cfg1' ibT1' ibUT1' ls1' where ss1': "ss1' = (cfg1', ibT1', ibUT1', ls1')"
            by (cases ss1', auto) 
          obtain cfg2' ibT2' ibUT2' ls2' where ss2': "ss2' = (cfg2', ibT2', ibUT2', ls2')"
            by (cases ss2', auto)

          obtain pc1' vs1' avst1' h1' p1' where 
            cfg1': "cfg1' = Config pc1' (State (Vstore vs1') avst1' h1' p1')"
            by (cases cfg1') (metis state.collapse vstore.collapse)
          obtain pc2' vs2' avst2' h2' p2' where 
            cfg2': "cfg2' = Config pc2' (State (Vstore vs2') avst2' h2' p2')"
            by (cases cfg2') (metis state.collapse vstore.collapse)
          note cfg = cfg cfg1' cfg2'

          obtain hh1' where h1': "h1' = Heap hh1'" by(cases h1', auto)
          obtain hh2' where h2': "h2' = Heap hh2'" by(cases h2', auto)
          note hh = hh h1' h2'

          note ss = ss1 ss2 ss1' ss2'
          have v':"(cfg1, ibT1, ibUT1) →B (cfg1', ibT1', ibUT1')" using v unfolding ss by simp
          then have v1:"nextB (cfg1, ibT1, ibUT1) = (cfg1', ibT1', ibUT1')" using stepB_nextB by auto

          have v'':"(cfg2, ibT2, ibUT2) →B (cfg2', ibT2', ibUT2')" using v unfolding ss by simp
          then have v2:"nextB (cfg2, ibT2, ibUT2) = (cfg2', ibT2', ibUT2')" using stepB_nextB by auto
          note valid = v' v1 v'' v2 

          have ls1':"ls1' = ls1  readLocs cfg1" using v unfolding ss by simp
          have ls2':"ls2' = ls2  readLocs cfg2" using v unfolding ss by simp
          note ls = ls1' ls2'


          note Γ_simps = cfg ls vsi_defs hh array_loc_def 
                          array_base_def state_def PC_def

          show "Γ_inv ss1' sl1' ss2' sl2'" 
            using Γ valid getAct
            unfolding ss apply-apply(frule Γ_implies)
            using cases_5[of "pc1"] not6 apply(elim disjE, simp_all)
            unfolding Γ_def ss
            prefer 4 subgoal using vs_xx_cases[of cfg1]
            by (elim disjE, unfold Γ_defs, auto simp add: Γ_simps) 
            subgoal by (unfold Γ_defs, auto simp add: Γ_simps) 
            subgoal by (unfold Γ_defs, auto simp add: Γ_simps) 
            subgoal by (unfold Γ_defs, auto simp add: Γ_simps)
            subgoal using val_neq_1 apply (unfold Γ_defs, auto simp add: Γ_simps) 
              using val_neq_1 by (metis NN_suc add_left_cancel nat_int) 
            subgoal by (unfold Γ_defs, auto simp add: Γ_simps) 
            subgoal by (unfold Γ_defs, auto simp add: Γ_simps) .
        qed
      qed
    qed


theorem "¬rsecure"
  apply(rule unwindSD_rsecure[of s30 s3_trans s40 s4_trans Γ_inv]) 
  by simp_all

end