Extensibella Example: exactEval:security

Language Specification

File: syntax.sos

[Reduce File] [Raw File]
Module exactEval:security

Builds on exactEval:host

stmt ::= ...
       | secdecl(slev, typ, string, expr)


--------------------------------------- [Proj-Secdecl]
Names |{stmt}- secdecl(L, Ty, X, E) ~~>
               declare(Ty, X, E)



fun ::= ...
        /*secfun(name, ret ty, ret lev, ret var, init ret var val,
                 params, body)*/
      | secfun(string, typ, slev, string, value, [param], stmt)


----------------------------------------------------- [Proj-SecFun]
|{fun}- secfun(Name, RetTy, RetLev, RetVar, RVVal,
               Params, Body) ~~>
        fun(Name, RetTy, RetVar, RVVal, Params, Body)



param ::= ...
        | secparam(string, typ, slev)


--------------------------------------------------- [Proj-SecParam]
|{param}- secparam(Name, Ty, L) ~~> param(Name, Ty)



slev ::= private
       | public
Projection slev :



exprNames Scope::Ctx E N
-------------------------------------------- [SN-Secdecl]
{stmtNames Scope::Ctx secdecl(L, Ty, X, E) N
           (X::Scope)::Ctx}





no_lookup Scope X /*can't redeclare in scope*/
typeOf FC Scope::RestTC E Ty
--------------------------------------------- [T-Secdecl]
{stmtOK FC Scope::RestTC secdecl(L, Ty, X, E)
           ((X, Ty)::Scope)::RestTC}


/*check the function is well-typed with given types*/
paramTys Params ParamTys
stmtOK FC [(RetVar, RetTy)::ParamTys] Body FinalTC
/*check the function ctx contains the given types for this function*/
lookup FC FunName (RetTy, PTys)
values ParamTys PTys
/*no param with same name as return variable*/
no_lookup ParamTys RetVar
valueType RVVal RetTy
------------------------------------------------------ [T-SecFun]
funOK FC secfun(FunName, RetTy, RetLev, RetVar, RVVal,
                Params, Body)


paramTys Params NameTys
values NameTys PTys
--------------------------------------------------------- [GFI-SecFun]
{getFunInfo secfun(FunName, RetTy, RetLev, RetVar, RVVal,
                   Params, Body) FunName RetTy PTys}


------------------------------------- [PT-SecParam]
paramTy secparam(Name, Ty, L) Name Ty





evalExpr FE EE E V Scope::EE1 O
---------------------------------------------------------- [E-Secdecl]
evalStmt FE EE secdecl(L, Ty, X, E) ((X, V)::Scope)::EE1 O


paramNames Params PNames
-------------------------------------------------------- [GFEI-SecFun]
{getFunEvalInfo secfun(FunName, RetTy, RetLev, RetVar,
                       RVVal, Params, Body)
    FunName RetVar RVVal PNames Body}


------------------------------------ [PN-SecParam]
paramName secparam(Name, Ty, L) Name

File: analysis.sos

[Reduce File] [Raw File]
Module exactEval:security

/*
  The type [[(string, slev)]] is a set of scopes for security typing.
  As with typing and evaluation, the most recent scope is first.

  The type [(string, (slev, [slev]))] is the function context, listing
  the known functions with their return security slevs and argument
  security slevs.
*/
            /*fun ctx, level ctx, program counter, expression, level*/
Judgment level : {[(string, (slev, [slev]))] [[(string, slev)]] slev
                  expr* slev}
Fixed Judgment levelArgs : {
   [(string, (slev, [slev]))] [[(string, slev)]] slev args [slev]}
Fixed Judgment levelRecFields : {
   [(string, (slev, [slev]))] [[(string, slev)]] slev recFieldExprs slev}

     /*fun ctx, level ctx, programm counter, stmt, updated level ctx*/
Judgment secure : {[(string, (slev, [slev]))] [[(string, slev)]]
                   slev stmt* [[(string, slev)]]}

Judgment funSecure : [(string, (slev, [slev]))] fun*
Fixed Judgment paramSecs : [param] [(string, slev)]
Judgment paramSec : param* string slev
Fixed Judgment funsSecure : [(string, (slev, [slev]))] [fun]

Judgment getFunSec : fun* string slev [slev]
Fixed Judgment gatherFunSecCtx : [fun] [(string, (slev, [slev]))]

                   /*program, security levels of arguments to main*/
Judgment programSecure : program* [slev]





/********************************************************************
 Maximum of Security Levels
 ********************************************************************/

Judgment join : slev* slev slev

------------------------- [J-Public]
join public public public


---------------------- [J-Private-L]
join private L private


---------------------- [J-Private-R]
join L private private





/********************************************************************
 Expression, Argument, and Record Field Levels
 ********************************************************************/

---------------------------- [L-Num]
level SF SG Sl num(I) public


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
----------------------------- [L-Plus]
level SF SG Sl plus(E1, E2) L


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
------------------------------ [L-Minus]
level SF SG Sl minus(E1, E2) L


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
----------------------------- [L-Mult]
level SF SG Sl mult(E1, E2) L


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
---------------------------- [L-Div]
level SF SG Sl div(E1, E2) L


-------------------------- [L-True]
level SF SG Sl true public


--------------------------- [L-False]
level SF SG Sl false public


/*Because of short-circuiting evaluation, we need to treat and and or
  like ifThenElse, incorportaing the level of E1 into the PC of E2*/
level SF SG Sl E1 L1
join L1 Sl Sl1
level SF SG Sl1 E2 L2
join L1 L2 L
---------------------------- [L-And]
level SF SG Sl and(E1, E2) L


level SF SG Sl E1 L1
join L1 Sl Sl1
level SF SG Sl1 E2 L2
join L1 L2 L
--------------------------- [L-Or]
level SF SG Sl or(E1, E2) L


level SF SG Sl E L
----------------------- [L-Not]
level SF SG Sl not(E) L


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
-------------------------------- [L-Greater]
level SF SG Sl greater(E1, E2) L


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
--------------------------- [L-Eq]
level SF SG Sl eq(E1, E2) L


---------------------------------- [L-String]
level SF SG Sl stringLit(S) public


level SF SG Sl E1 L1
level SF SG Sl E2 L2
join L1 L2 L
---------------------------------- [L-AppString]
level SF SG Sl appString(E1, E2) L


lookupScopes X SG L
------------------------ [L-Name]
level SF SG Sl name(X) L


/*in private contexts, only private functions so we don't leak where
  we are by function output*/
lookup SF Fun (private, ArgLevs)
levelArgs SF SG private Args ArgLevs
------------------------------------------- [L-Call-Private]
level SF SG private call(Fun, Args) private


lookup SF Fun (RetLev, ArgLevs)
levelArgs SF SG public Args ArgLevs
----------------------------------------- [L-Call-Public]
level SF SG public call(Fun, Args) RetLev


secure SF []::SG Sl S SG1
level SF SG1 Sl E L
------------------------------- [L-StmtExpr]
level SF SG Sl stmtExpr(S, E) L


levelRecFields SF SG Sl Fields L
--------------------------------- [L-RecBuild]
level SF SG Sl recBuild(Fields) L


level SF SG Sl E L
----------------------------------------- [L-RecAccess]
level SF SG Sl recFieldAccess(E, Field) L


level SF SG Sl Msg L
----------------------------------- [L-Error]
level SF SG Sl errorExpr(Msg, Ty) L


names SG Names
Names |{expr}- E ~~> E_P
level SF SG Sl E_P L
------------------------ [L-Default]*
level SF SG Sl E L





============================= [LA-Nil]
levelArgs SF SG Sl nilArgs []


level SF SG Sl E L
levelArgs SF SG Sl A Rest
========================================= [LA-Cons]
levelArgs SF SG Sl consArgs(E, A) L::Rest





=============================================== [LRF-Nil]
levelRecFields SF SG Sl nilRecFieldExprs public


level SF SG Sl E LE
levelRecFields SF SG Sl RF LRF
join LE LRF L
===================================================== [LRF-Cons]
levelRecFields SF SG Sl consRecFieldExprs(F, E, RF) L





/********************************************************************
 Statement Security
 ********************************************************************/

----------------------- [S-Noop]
secure LF SG Sl noop SG


secure SF SG Sl S1 SG1
secure SF SG1 Sl S2 SG2
------------------------------- [S-Seq]
secure SF SG Sl seq(S1, S2) SG2


level SF Scope::SG public E public
no_lookup Scope X
--------------------------------------------- [S-Declare]
{secure SF Scope::SG public declare(Ty, X, E)
        ((X, public)::Scope)::SG}


level SF SG Sl E L
lookupScopes X SG private
------------------------------- [S-Assign-Private]
secure SF SG Sl assign(X, E) SG


level SF SG public E public
lookupScopes X SG public
----------------------------------- [S-Assign-Public]
secure SF SG public assign(X, E) SG


level SF SG Sl E L
lookupScopes Rec SG private
-------------------------------------------- [S-RecUpdate-Private]
secure SF SG Sl recUpdate(Rec, Fields, E) SG


level SF SG public E public
lookupScopes Rec SG public
------------------------------------------------ [S-RecUpdate-Public]
secure SF SG public recUpdate(Rec, Fields, E) SG


level SF SG Sl E L
join L Sl Sl1
secure SF []::SG Sl1 T SGT
secure SF []::SG Sl1 F SGF
-------------------------------------- [S-IfThenElse]
secure SF SG Sl ifThenElse(E, T, F) SG


/*
  We need to split security for while loops into public and private
  cases because our expressions can set variables.  If the condition
  could set public variables (program counter public) but the level of
  the condition be private, we could have two evalutaions of the loop,
  one that immediately uses E-While-False and one that uses
  E-While-True a few times.  This would set the public variable once
  in the former case but multiple times in the latter, making the
  values of the public variables differ.  Splitting it allows us to
  ensure we do not set public variables multiple times in one run but
  not another.
*/
level SF SG private E L /*safe to have any level here*/
secure SF []::SG private S Scope::SG1
------------------------------------- [S-While-Private]
secure SF SG private while(E, S) SG


level SF SG public E public
secure SF []::SG public S Scope::SG1
------------------------------------ [S-While-Public]
secure SF SG public while(E, S) SG


secure SF []::SG Sl S Scope::SG
------------------------------- [S-ScopeStmt]
secure SF SG Sl scopeStmt(S) SG


/*only print public values in public situations*/
level SF SG public E public
---------------------------------- [S-Print]
secure SF SG public printVal(E) SG


level SF Scope::SG Sl E L
no_lookup Scope X
-------------------------------------------------- [S-Secdecl-Private]
{secure SF Scope::SG Sl secdecl(private, Ty, X, E)
        ((X, private)::Scope)::SG}


level SF Scope::SG public E public
no_lookup Scope X
--------------------------------------- [S-Secdecl-Public]
{secure SF Scope::SG public
              secdecl(public, Ty, X, E)
           ((X, public)::Scope)::SG}


names SG Names
Names |{stmt}- S ~~> S_P
secure SF SG Sl S_P SG1
------------------------ [S-Default]*
secure SF SG Sl S SG1





/********************************************************************
 Function Security
 ********************************************************************/

/*
  Note we check function bodies are secure with the program counter
  starting at the level of the returned variable.  This ensures we can
  set the return variable in the body of the function if it is
  private.  A different approach might be useful for writing programs,
  but this works for reasoning.
*/

/*check the function is secure with given info*/
paramSecs Params ParamSecs
secure SF [(RetVar, public)::ParamSecs] public Body SG
/*check the function ctx agrees with this information*/
lookup SF FunName (public, PSecs)
values ParamSecs PSecs
------------------------------------------------------ [FS-Fun]
funSecure SF fun(FunName, RetTy, RetVar, RVVal,
                 Params, Body)


/*check the function is secure with given info*/
paramSecs Params ParamSecs
secure SF [(RetVar, RetLev)::ParamSecs] RetLev Body SG
/*check the function ctx agrees with this information*/
lookup SF FunName (RetLev, PSecs)
values ParamSecs PSecs
---------------------------------------------------------- [FS-SecFun]
funSecure SF secfun(FunName, RetTy, RetLev, RetVar, RVVal,
                    Params, Body)


|{fun}- F ~~> F_P
funSecure SF F_P
----------------- [FS-Default]*
funSecure SF F




================ [FSs-Nil]
funsSecure SF []


funSecure SF F
funsSecure SF Rest
===================== [FSs-Cons]
funsSecure SF F::Rest




------------------------------------ [PS-Param]
paramSec param(Name, Ty) Name public


------------------------------------- [PS-SecParam]
paramSec secparam(Name, Ty, L) Name L


|{param}- P ~~> P_P
paramSec P_P Name L
------------------- [PS-Default]*
paramSec P Name L




=============== [PSs-Nil]
paramSecs [] []


paramSec P Name L
paramSecs PRest SRest
=================================== [PSs-Cons]
paramSecs P::PRest (Name, L)::SRest





/********************************************************************
 Gather Function Information
 ********************************************************************/

paramSecs Params ParamSecs
values ParamSecs PSecs
--------------------------------------------- [GFS-Fun]
getFunSec fun(Name, RetTy, RetVar, RVVal,
              Params, Body) Name public PSecs


paramSecs Params ParamSecs
values ParamSecs PSecs
---------------------------------------------------- [GFS-SecFun]
getFunSec secfun(Name, RetTy, RetLev, RetVar, RVVal,
                 Params, Body) Name RetLev PSecs


|{fun}- F ~~> F_P
getFunSec F_P Name Lev PSecs
---------------------------- [GFS-Default]*
getFunSec F Name Lev PSecs




===================== [GFSC-Nil]
gatherFunSecCtx [] []


getFunSec F Name Lev PSecs
gatherFunSecCtx FRest SRest
==================================================== [GFSC-Cons]
gatherFunSecCtx F::FRest (Name, (Lev, PSecs))::SRest





/********************************************************************
 Program Security
 ********************************************************************/

gatherFunSecCtx Funs SF
getFunSec Main Name RetLev PSecs
funsSecure (Name, (RetLev, PSecs))::SF Funs
funSecure (Name, (RetLev, PSecs))::SF Main
------------------------------------------- [SP-Program]
programSecure program(Funs, Main) PSecs


|{program}- P ~~> P_P
programSecure P_P PSecs
----------------------- [SP-Default]*
programSecure P PSecs

Reasoning

[Show All Proofs] [Hide All Proofs] [Raw File]

Click on a command or tactic to see a detailed view of its use.

Module exactEval:security.


Prove_Constraint exactEval:host:proj_expr_unique.
Prove_Constraint exactEval:host:proj_expr_is.
Prove_Constraint exactEval:host:proj_expr_other.

Prove_Constraint exactEval:host:proj_stmt_unique. [Show Proof]

Prove_Constraint exactEval:host:proj_stmt_is. [Show Proof]

Prove_Constraint exactEval:host:proj_stmt_other. [Show Proof]


Prove_Constraint exactEval:host:proj_fun_unique. [Show Proof]

Prove_Constraint exactEval:host:proj_fun_is. [Show Proof]


Prove_Constraint exactEval:host:proj_param_unique. [Show Proof]

Prove_Constraint exactEval:host:proj_param_is. [Show Proof]


Prove_Constraint exactEval:host:proj_program_unique.
Prove_Constraint exactEval:host:proj_program_is.

Prove_Constraint exactEval:host:proj_typ_unique.
Prove_Constraint exactEval:host:proj_typ_is.


Extensible_Theorem
  is_slev_public_or_not : forall L,
    IsL : is_slev L ->
    L = public \/ (L = public -> false)
  on IsL. [Show Proof]

Extensible_Theorem
  is_slev_private_or_not : forall L,
    IsL : is_slev L ->
    L = private \/ (L = private -> false)
  on IsL. [Show Proof]

Extensible_Theorem
  is_slev_eq_or_not : forall L1 L2,
    IsL1 : is_slev L1 ->
    IsL2 : is_slev L2 ->
    L1 = L2 \/ (L1 = L2 -> false)
  on IsL1. [Show Proof]


Add_Proj_Rel exactEval:host:is_expr, exactEval:host:is_args,
             exactEval:host:is_recFieldExprs, exactEval:host:is_stmt.
Prove_Ext_Ind exactEval:host:is_expr, exactEval:host:is_args,
              exactEval:host:is_recFieldExprs, exactEval:host:is_stmt. [Show Proof]


Prove exactEval:host:is_args_nilArgs_or_consArgs.
Prove exactEval:host:is_recFieldExprs_nilRecFieldExprs_or_consRecFieldExprs.


Prove exactEval:host:vars_unique.
Prove exactEval:host:vars_is.
Prove exactEval:host:vars_exist,
      exactEval:host:varsArgs_exist,
      exactEval:host:varsRecFields_exist.


Prove exactEval:host:stmtNames_is,
      exactEval:host:stmtNames_isCtx,
      exactEval:host:exprNames_is. [Show Proof]


Prove exactEval:host:stmtNames_unique,
      exactEval:host:exprNames_unique. [Show Proof]


Prove exactEval:host:stmtNames_keep_older. [Show Proof]


Prove exactEval:host:stmtNames_exists,
      exactEval:host:exprNames_exists,
      exactEval:host:argsNames_exists,
      exactEval:host:recFieldNames_exists. [Show Proof]


Prove exactEval:host:stmtNames_not_in_ctx,
      exactEval:host:exprNames_not_in_ctx. [Show Proof]


Prove exactEval:host:stmtNames_relatedCtxs,
      exactEval:host:stmtNames_relatedCtxs_ctx_fwd,
      exactEval:host:stmtNames_relatedCtxs_ctx_back,
      exactEval:host:exprNames_relatedCtxs. [Show Proof]



Prove exactEval:host:stmtNames_increaseCtxs,
      exactEval:host:stmtNames_increaseCtxs_ctxs,
      exactEval:host:exprNames_increaseCtxs. [Show Proof]


Prove_Constraint exactEval:host:proj_exprNames.

Prove_Constraint exactEval:host:proj_stmtNames. [Show Proof]


Prove_Constraint exactEval:host:proj_stmtNames_names_forward. [Show Proof]


Prove_Constraint exactEval:host:proj_stmtNames_names_backward. [Show Proof]


Prove exactEval:host:typeOf_isTy,
      exactEval:host:stmtOK_isCtx. [Show Proof]


Prove exactEval:host:stmtOK_keep_scopes. [Show Proof]

Prove exactEval:host:stmtOK_older_scopes_same. [Show Proof]

Prove exactEval:host:stmtOK_first_scope_lookup_same. [Show Proof]


Prove exactEval:host:typeOf_unique,
      exactEval:host:stmtOK_unique. [Show Proof]



Prove exactEval:host:paramTy_is. [Show Proof]

Prove exactEval:host:getFunInfo_is. [Show Proof]


Prove exactEval:host:paramTy_exists. [Show Proof]

Prove exactEval:host:getFunInfo_exists. [Show Proof]



Prove exactEval:host:evalExpr_isCtx,
      exactEval:host:evalExpr_isValue,
      exactEval:host:evalStmt_isCtx,
      exactEval:host:evalArgs_isCtx,
      exactEval:host:evalArgs_isValue,
      exactEval:host:evalRecFields_isCtx,
      exactEval:host:evalRecFields_isValue. [Show Proof]


Prove exactEval:host:evalExpr_isOutput,
      exactEval:host:evalStmt_isOutput,
      exactEval:host:evalArgs_isOutput,
      exactEval:host:evalRecFields_isOutput. [Show Proof]



Prove exactEval:host:paramName_is. [Show Proof]

Prove exactEval:host:getFunEvalInfo_is. [Show Proof]



Prove exactEval:host:evalProgram_isOutput.


Prove exactEval:host:evalExpr_names_same,
      exactEval:host:evalStmt_names_same,
      exactEval:host:evalArgs_names_same,
      exactEval:host:evalRecFields_names_same. [Show Proof]



Prove exactEval:host:evalExpr_newNameScopes,
      exactEval:host:evalExpr_newNameScopes_output,
      exactEval:host:evalExpr_newNameScopes_ctx,
      exactEval:host:evalStmt_newNameScopes_output,
      exactEval:host:evalStmt_newNameScopes,
      exactEval:host:evalArgs_newNameScopes,
      exactEval:host:evalArgs_newNameScopes_output,
      exactEval:host:evalArgs_newNameScopes_ctx,
      exactEval:host:evalRecFields_newNameScopes,
      exactEval:host:evalRecFields_newNameScopes_output,
      exactEval:host:evalRecFields_newNameScopes_ctx. [Show Proof]


Add_Ext_Size exactEval:host:evalExpr,
             exactEval:host:evalArgs,
             exactEval:host:evalRecFields,
             exactEval:host:evalStmt.
Add_Proj_Rel exactEval:host:evalExpr,
             exactEval:host:evalArgs,
             exactEval:host:evalRecFields,
             exactEval:host:evalStmt.

Prove exactEval:host:evalExpr_newNameScopes_exists_ES,
      exactEval:host:evalStmt_newNameScopes_exists_ES,
      exactEval:host:evalArgs_newNameScopes_exists_ES,
      exactEval:host:evalRecFields_newNameScopes_exists_ES. [Show Proof]


Prove exactEval:host:evalExpr_ctx_names,
      exactEval:host:evalStmt_ctx_names,
      exactEval:host:evalArgs_ctx_names,
      exactEval:host:evalRecFields_ctx_names. [Show Proof]


Prove exactEval:host:evalExpr_newNameScopes_exists_back,
      exactEval:host:evalStmt_newNameScopes_exists_back,
      exactEval:host:evalArgs_newNameScopes_exists_back,
      exactEval:host:evalRecFields_newNameScopes_exists_back. [Show Proof]


Prove exactEval:host:evalExpr_scopes_same,
      exactEval:host:evalExpr_scopes_same_ctx,
      exactEval:host:evalStmt_scopes_same,
      exactEval:host:evalStmt_scopes_same_ctx,
      exactEval:host:evalArgs_scopes_same,
      exactEval:host:evalArgs_scopes_same_ctx,
      exactEval:host:evalRecFields_scopes_same,
      exactEval:host:evalRecFields_scopes_same_ctx. [Show Proof]


Prove exactEval:host:evalExpr_scopes_same_exists,
      exactEval:host:evalStmt_scopes_same_exists,
      exactEval:host:evalArgs_scopes_same_exists,
      exactEval:host:evalRecFields_scopes_same_exists. [Show Proof]


Prove_Constraint exactEval:host:proj_evalExpr_forward.
Prove_Constraint exactEval:host:proj_evalExpr_backward.

Prove_Constraint exactEval:host:proj_evalStmt_forward. [Show Proof]

Prove_Constraint exactEval:host:proj_evalStmt_backward. [Show Proof]


Prove_Ext_Ind exactEval:host:evalExpr,
              exactEval:host:evalArgs,
              exactEval:host:evalRecFields,
              exactEval:host:evalStmt. [Show Proof]



Prove exactEval:host:paramName_unique. [Show Proof]


Prove_Constraint exactEval:host:proj_paramName_forward. [Show Proof]

Prove_Constraint exactEval:host:proj_paramName_back. [Show Proof]


Prove exactEval:host:getFunEvalInfo_unique. [Show Proof]



Prove_Constraint exactEval:host:proj_getFunEvalInfo_forward. [Show Proof]

Prove_Constraint exactEval:host:proj_getFunEvalInfo_back. [Show Proof]


Prove exactEval:host:evalProgram_unique.

Prove_Constraint exactEval:host:proj_evalProgram_forward.
Prove_Constraint exactEval:host:proj_evalProgram_back.


Prove exactEval:host:evalExpr_typePres_ctx,
      exactEval:host:evalExpr_typePres,
      exactEval:host:evalStmt_typePres,
      exactEval:host:evalArgs_typePres_Ctx,
      exactEval:host:evalArgs_typePres,
      exactEval:host:evalRecFields_typePres_Ctx,
      exactEval:host:evalRecFields_typePres. [Show Proof]


Prove exactEval:host:paramTy_paramName_same. [Show Proof]

Prove exactEval:host:funOK_getFunEvalInfo_related. [Show Proof]



Prove exactEval:host:evalExpr_output_forms,
      exactEval:host:evalStmt_output_forms,
      exactEval:host:evalArgs_output_forms,
      exactEval:host:evalRecFields_output_forms. [Show Proof]


Prove exactEval:host:evalProgram_output_forms.


Prove exactEval:host:paramName_exists. [Show Proof]

Prove exactEval:host:getFunEvalInfo_exists. [Show Proof]






/********************************************************************
    _____                      _ _
  / ____|                    (_) |
 | (___   ___  ___ _   _ _ __ _| |_ _   _
  \___ \ / _ \/ __| | | | '__| | __| | | |
  ____) |  __/ (__| |_| | |  | | |_| |_| |
 |_____/ \___|\___|\__,_|_|  |_|\__|\__, |
                                     __/ |
  _____                           _ |___/
 |  __ \                         | | (_)
 | |__) | __ ___  _ __   ___ _ __| |_ _  ___  ___
 |  ___/ '__/ _ \| '_ \ / _ \ '__| __| |/ _ \/ __|
 | |   | | | (_) | |_) |  __/ |  | |_| |  __/\__ \
 |_|   |_|  \___/| .__/ \___|_|   \__|_|\___||___/
                 | |
                 |_|
 Security Properties
 ********************************************************************/

/********************************************************************
 Properties about join
 ********************************************************************/
Extensible_Theorem
  join_is : forall L1 L2 R,
    Is1 : is_slev L1 ->
    Is2 : is_slev L2 ->
    J : join L1 L2 R ->
    is_slev R
  on J. [Show Proof]



%need this because we can't analyze it due to restrictions
Extensible_Theorem
  join_private_right : forall L R,
    Is : is_slev L ->
    J : join L private R ->
    R = private
  on J. [Show Proof]



Extensible_Theorem
  join_unique : forall L1 L2 LA LB,
    Is1 : is_slev L1 ->
    Is2 : is_slev L2 ->
    JA : join L1 L2 LA ->
    JB : join L1 L2 LB ->
    LA = LB
  on JA. [Show Proof]



Extensible_Theorem
  join_private : forall L1 L2,
    Is1 : is_slev L1 ->
    Is2 : is_slev L2 ->
    J : join L1 L2 private ->
    L1 = private \/ L2 = private
  on J. [Show Proof]



Extensible_Theorem
  join_public : forall L1 L2,
    Is1 : is_slev L1 ->
    Is2 : is_slev L2 ->
    J : join L1 L2 public ->
    L1 = public /\ L2 = public
  on J. [Show Proof]





/********************************************************************
 Security is
 ********************************************************************/
Theorem lookup_is_slev : forall L X Lev,
  is_list (is_pair is_string is_slev) L -> lookup L X Lev ->
  is_slev Lev. [Show Proof]



Theorem lookupScopes_is_slev : forall SG X Lev,
  is_list (is_list (is_pair is_string is_slev)) SG ->
  lookupScopes X SG Lev -> is_slev Lev. [Show Proof]



Theorem lookupSecFun_is : forall SF F Lev PLs,
  is_list (is_pair is_string
          (is_pair is_slev (is_list is_slev))) SF ->
  lookup SF F (Lev, PLs) -> is_slev Lev /\ is_list is_slev PLs. [Show Proof]



Theorem domain_is_sec : forall L D,
  is_list (is_pair is_string is_slev) L -> domain L D ->
  is_list is_string D. [Show Proof]



Theorem names_is_sec : forall SG Names,
  is_list (is_list (is_pair is_string is_slev)) SG ->
  names SG Names -> is_list is_string Names. [Show Proof]



Theorem mem_is_sec : forall L IDS,
  is_list (is_pair is_string is_slev) L -> mem IDS L ->
  is_pair is_string is_slev IDS. [Show Proof]



Extensible_Theorem
  level_is : forall SF SG PC E L,
    IsE : is_expr E ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    Lev : level SF SG PC E L ->
    is_slev L
  on Lev as IH_E,
  secure_is : forall SF SG PC S SG',
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    Sec : secure SF SG PC S SG' ->
    is_list (is_list (is_pair is_string is_slev)) SG'
  on Sec as IH_S
also
  levelArgs_is : forall SF SG PC A L,
    IsA : is_args A ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    Lev : levelArgs SF SG PC A L ->
    is_list is_slev L
  on Lev as IH_A,
  levelRecFields_is : forall SF SG PC RF L,
    IsRF : is_recFieldExprs RF ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    Lev : levelRecFields SF SG PC RF L ->
    is_slev L
  on Lev as IH_RF. [Show Proof]





/********************************************************************
 Uniqueness of security
 ********************************************************************/
Extensible_Theorem
  level_unique : forall SF SG PC E LA LB,
    IsE : is_expr E ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    LevA : level SF SG PC E LA ->
    LevB : level SF SG PC E LB ->
    LA = LB
  on LevA as IH_E,
  secure_unique : forall SF SG PC S SGA SGB,
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    SecA : secure SF SG PC S SGA ->
    SecB : secure SF SG PC S SGB ->
    SGA = SGB
  on SecA as IH_S
also
  levelArgs_unique : forall SF SG PC A LA LB,
    IsA : is_args A ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    LevA : levelArgs SF SG PC A LA ->
    LevB : levelArgs SF SG PC A LB ->
    LA = LB
  on LevA as IH_A,
  levelRecFields_unique : forall SF SG PC RF LA LB,
    IsRF : is_recFieldExprs RF ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    LevA : levelRecFields SF SG PC RF LA ->
    LevB : levelRecFields SF SG PC RF LB ->
    LA = LB
  on LevA as IH_RF. [Show Proof]





/********************************************************************
 Uniqueness of security
 ********************************************************************/
Extensible_Theorem
  secure_older_scopes : forall SF Scope SG PC S SG',
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev))
              (Scope::SG) ->
    Sec : secure SF (Scope::SG) PC S SG' ->
    exists Scope', SG' = Scope'::SG /\
       (forall X L, lookup Scope X L -> lookup Scope' X L)
  on Sec. [Show Proof]





/********************************************************************
 Names in contexts related
 ********************************************************************/
Theorem names_same_scopes_same[V] :
  forall A B (C : list (list (pair string V))),
    is_list (is_list (is_pair is_string is_value)) A ->
    is_list (is_list (is_pair is_string is_value)) B ->
    names_same A C -> scopes_same A B -> names_same B C. [Show Proof]



Theorem zip_names_same[A, B] :
  forall (Names : list string) (A : list A) (B : list B) ZA ZB,
    zip Names A ZA -> zip Names B ZB -> names_same [ZA] [ZB]. [Show Proof]



Extensible_Theorem
  level_eval_names_same : forall E SF SG PC L FE EE V EE' O,
    IsE : is_expr E ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
    NS : names_same EE SG ->
    Ev : evalExpr FE EE E V EE' O ->
    Lev : level SF SG PC E L ->
    names_same EE' SG
  on Ev,
  secure_eval_names_same : forall S SF SG PC SG' FE Scope EE EE' O,
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE : is_list (is_list (is_pair is_string is_value))
              (Scope::EE) ->
    NS : names_same (Scope::EE) SG ->
    Ev : evalStmt FE (Scope::EE) S EE' O ->
    Sec : secure SF SG PC S SG' ->
    names_same EE' SG'
  on Ev,
  levelArgs_eval_names_same : forall A SF SG PC L FE EE V EE' O,
    IsA : is_args A ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
    NS : names_same EE SG ->
    Ev : evalArgs FE EE A V EE' O ->
    Lev : levelArgs SF SG PC A L ->
    names_same EE' SG
  on Ev,
  levelRecFields_eval_names_same : forall RF SF SG PC L FE EE V EE' O,
    IsRF : is_recFieldExprs RF ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
    NS : names_same EE SG ->
    Ev : evalRecFields FE EE RF V EE' O ->
    Lev : levelRecFields SF SG PC RF L ->
    names_same EE' SG
  on Ev. [Show Proof]





/********************************************************************
 Properties of public_equiv
 ********************************************************************/
Define public_equiv :
  list (list (pair string slev)) -> list (list (pair string value)) ->
  list (list (pair string value)) -> prop by
public_equiv [] [] [];
public_equiv (SScope::S) (Scope1::G1) (Scope2::G2) :=
  %lookup same for public
  (forall X V,
      lookup SScope X public -> lookup Scope1 X V ->
      lookup Scope2 X V) /\
  (forall X V,
      lookup SScope X public -> lookup Scope2 X V ->
      lookup Scope1 X V) /\
  %rest
  public_equiv S G1 G2.


Theorem no_lookup_names_same : forall A B X,
  is_list (is_pair is_string is_value) B ->
  (forall X IB, mem (X, IB) B ->
      exists (IA : value), mem (X, IA) A) ->
  no_lookup A X -> no_lookup B X. [Show Proof]



Theorem public_equiv_lookupScopes : forall S G1 G2 X V,
  public_equiv S G1 G2 -> names_same G1 S -> names_same G2 S ->
  is_list (is_list (is_pair is_string is_value)) G2 ->
  lookupScopes X S public ->
  lookupScopes X G1 V -> lookupScopes X G2 V. [Show Proof]



Theorem public_equiv_trans : forall SG GA GB GC,
  public_equiv SG GA GB -> public_equiv SG GB GC ->
  public_equiv SG GA GC. [Show Proof]



Theorem public_equiv_refl : forall SG G,
  names_same G SG -> public_equiv SG G G. [Show Proof]



Theorem public_equiv_symm : forall SG GA GB,
  public_equiv SG GA GB -> public_equiv SG GB GA. [Show Proof]



Theorem public_equiv_scopes_same_snd : forall SG G GA GB,
  public_equiv SG G GB -> scopes_same GA GB -> public_equiv SG G GA. [Show Proof]



Theorem public_equiv_scopes_same_fst : forall SG G GA GB,
  public_equiv SG GB G -> scopes_same GA GB -> public_equiv SG GA G. [Show Proof]



Theorem public_equiv_add_scope : forall SG GA GB,
  public_equiv SG GA GB -> public_equiv ([]::SG) ([]::GA) ([]::GB). [Show Proof]



Theorem public_equiv_add_public : forall SS SG AS GA BS GB X V,
  public_equiv (SS::SG) (AS::GA) (BS::GB) ->
  public_equiv (((X, public)::SS)::SG) (((X, V)::AS)::GA)
                                       (((X, V)::BS)::GB). [Show Proof]



Theorem public_equiv_add_other : forall SS SG AS GA BS GB X L VA VB,
  public_equiv (SS::SG) (AS::GA) (BS::GB) -> (L = public -> false) ->
  public_equiv (((X, L)::SS)::SG) (((X, VA)::AS)::GA)
                                  (((X, VB)::BS)::GB). [Show Proof]



Theorem remove_all_eq_or_mem[Key, Item] :
  forall L L' (X Y : Key) (V : Item),
    remove_all L X L' -> mem (Y, V) L -> Y = X \/ mem (Y, V) L'. [Show Proof]



Theorem public_equiv_replaceScopes_public : forall SG GA GB X V RA RB,
  public_equiv SG GA GB -> names_same GA SG -> names_same GB SG ->
  lookupScopes X SG public ->
  replaceScopes X V GA RA -> replaceScopes X V GB RB ->
  public_equiv SG RA RB. [Show Proof]



Theorem public_equiv_replaceScopes_other :
  forall SG GA GB X L VA VB RA RB,
    public_equiv SG GA GB -> names_same GA SG -> names_same GB SG ->
    lookupScopes X SG L -> (L = public -> false) ->
    replaceScopes X VA GA RA -> replaceScopes X VB GB RB ->
    public_equiv SG RA RB. [Show Proof]



Theorem replaceScopes_public_equiv : forall SG L X V L' SL,
  names_same L SG -> replaceScopes X V L L' -> lookupScopes X SG SL ->
  (SL = public -> false) -> public_equiv SG L L'. [Show Proof]





/********************************************************************
 No public changes in private contexts
 ********************************************************************/
Extensible_Theorem
  stmt_not_public_no_public_change :
    forall S SF SScope SG PC SG' FE Scope EE Scope' EE' O,
      IsS : is_stmt S ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev))
                (SScope::SG) ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value))
                (Scope::EE) ->
      NS : names_same (Scope::EE) (SScope::SG) ->
      Ev : evalStmt FE (Scope::EE) S (Scope'::EE') O ->
      Sec : secure SF (SScope::SG) PC S SG' ->
      NEq : (PC = public -> false) ->
      /*only the end of the ctxs are related, not the first scope*/
      public_equiv SG EE EE'
  on Ev as IH_S,
  expr_not_public_no_public_change :
    forall E SF SG PC L FE EE V EE' O,
      IsE : is_expr E ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      NS : names_same EE SG ->
      Ev : evalExpr FE EE E V EE' O ->
      Lev : level SF SG PC E L ->
      NEq : (PC = public -> false) ->
      public_equiv SG EE EE'
  on Ev as IH_E,
  args_not_public_no_public_change :
    forall A SF SG PC L FE EE V EE' O,
      IsA : is_args A ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      NS : names_same EE SG ->
      Ev : evalArgs FE EE A V EE' O ->
      Lev : levelArgs SF SG PC A L ->
      NEq : (PC = public -> false) ->
      public_equiv SG EE EE'
  on Ev as IH_A,
  recFields_not_public_no_public_change :
    forall RF SF SG PC L FE EE V EE' O,
      IsRF : is_recFieldExprs RF ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      NS : names_same EE SG ->
      Ev : evalRecFields FE EE RF V EE' O ->
      Lev : levelRecFields SF SG PC RF L ->
      NEq : (PC = public -> false) ->
      public_equiv SG EE EE'
  on Ev as IH_RF. [Show Proof]



Theorem while_no_public_change :
  forall SF SG PC SG' L Cond Body FE EE EE2 O,
    is_expr Cond -> is_stmt Body ->
    is_list (is_pair is_string
            (is_pair is_slev (is_list is_slev))) SF ->
    is_list (is_list (is_pair is_string is_slev)) SG ->
    is_slev PC ->
    is_list (is_pair is_string
            (is_pair is_string
            (is_pair is_value
            (is_pair (is_list is_string) is_stmt)))) FE ->
    is_list (is_list (is_pair is_string is_value)) EE ->
    names_same EE SG ->
    secure SF SG PC (while Cond Body) SG' ->
    level SF SG PC Cond L -> (L = public -> false) ->
    evalStmt FE EE (while Cond Body) EE2 O ->
    public_equiv SG EE EE2. [Show Proof]





/********************************************************************
 Evaluation does not leak private information
 ********************************************************************/
%all public argument values are the same; private ones may differ
Define level_arg_vals :
       list slev -> list value -> list value -> prop by
level_arg_vals [] [] [];
level_arg_vals (public::SRest) (V::ARest) (V::BRest) :=
   level_arg_vals SRest ARest BRest;
level_arg_vals (L::SRest) (VA::ARest) (VB::BRest) :=
   (L = public -> false) /\ level_arg_vals SRest ARest BRest.


Theorem zip_level_arg_vals : forall S A B N ZA ZB ZS,
  level_arg_vals S A B -> zip N A ZA -> zip N B ZB -> zip N S ZS ->
  public_equiv [ZS] [ZA] [ZB]. [Show Proof]



Theorem zip_is_sec : forall A B Z,
  is_list is_string A -> is_list is_slev B -> zip A B Z ->
  is_list (is_pair is_string is_slev) Z. [Show Proof]



%security and evaluation fun ctxs are appropriately related
Define secFunCtxs : list (pair string (pair slev (list slev))) ->
       list (pair string (pair string (pair value
            (pair (list string) stmt)))) -> prop by
secFunCtxs SF FE :=
  forall FName RetLev PSecs RetVar RVVal PNames Body,
    lookup SF FName (RetLev, PSecs) ->
    lookup FE FName (RetVar, RVVal, PNames, Body) ->
    exists ZP SG, zip PNames PSecs ZP /\
                  secure SF [(RetVar, RetLev)::ZP] RetLev Body SG.


Extensible_Theorem
  %evaluation under public_equiv ctxs yields public_equiv ctxs
  stmt_secure : forall S SF SG PC SG' FE ScopeA EE_A EE_A' OA
                       ScopeB EE_B EE_B' OB,
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE_A : is_list (is_list (is_pair is_string is_value))
                (ScopeA::EE_A) ->
    IsEE_B : is_list (is_list (is_pair is_string is_value))
                (ScopeB::EE_B) ->
    SFC : secFunCtxs SF FE ->
    NSA : names_same (ScopeA::EE_A) SG ->
    NSB : names_same (ScopeB::EE_B) SG ->
    PE : public_equiv SG (ScopeA::EE_A) (ScopeB::EE_B) ->
    Sec : secure SF SG PC S SG' ->
    EvA : evalStmt FE (ScopeA::EE_A) S EE_A' OA ->
    EvB : evalStmt FE (ScopeB::EE_B) S EE_B' OB ->
    public_equiv SG' EE_A' EE_B'
  on EvA as IH_S,
  expr_secure :
    forall E SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsE : is_expr E ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : level SF SG PC E L ->
      EvA : evalExpr FE EE_A E VA EE_A' OA ->
      EvB : evalExpr FE EE_B E VB EE_B' OB ->
      public_equiv SG EE_A' EE_B'
  on EvA as IH_E,
  args_secure :
    forall A SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsA : is_args A ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelArgs SF SG PC A L ->
      EvA : evalArgs FE EE_A A VA EE_A' OA ->
      EvB : evalArgs FE EE_B A VB EE_B' OB ->
      public_equiv SG EE_A' EE_B'
  on EvA as IH_A,
  recFields_secure :
    forall RF SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsRF : is_recFieldExprs RF ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelRecFields SF SG PC RF L ->
      EvA : evalRecFields FE EE_A RF VA EE_A' OA ->
      EvB : evalRecFields FE EE_B RF VB EE_B' OB ->
      public_equiv SG EE_A' EE_B'
  on EvA as IH_RF,
  %public terms produce the same values under public_equiv ctxs
  expr_level :
    forall E SF SG PC FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsE : is_expr E ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : level SF SG PC E public ->
      EvA : evalExpr FE EE_A E VA EE_A' OA ->
      EvB : evalExpr FE EE_B E VB EE_B' OB ->
      VA = VB
  on EvA as IH_E_L,
  recFields_level :
    forall RF SF SG PC FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsRF : is_recFieldExprs RF ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelRecFields SF SG PC RF public ->
      EvA : evalRecFields FE EE_A RF VA EE_A' OA ->
      EvB : evalRecFields FE EE_B RF VB EE_B' OB ->
      VA = VB
  on EvA as IH_RF_L,
  %arguments produce the same values for public ones
  args_level :
    forall A SF SG PC Ls FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsA : is_args A ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelArgs SF SG PC A Ls ->
      EvA : evalArgs FE EE_A A VA EE_A' OA ->
      EvB : evalArgs FE EE_B A VB EE_B' OB ->
      level_arg_vals Ls VA VB
  on EvA as IH_A_L. [Show Proof]



Extensible_Theorem
  stmt_not_public_no_output :
    forall S SF SG PC SG' FE Scope EE EE' O,
      IsS : is_stmt S ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value))
                (Scope::EE) ->
      SFC : secFunCtxs SF FE ->
      NS : names_same (Scope::EE) SG ->
      Ev : evalStmt FE (Scope::EE) S EE' O ->
      Sec : secure SF SG PC S SG' ->
      NEq : (PC = public -> false) ->
      O = []
  on Ev as IH_S,
  expr_not_public_no_output :
    forall E SF SG PC L FE EE V EE' O,
      IsE : is_expr E ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      SFC : secFunCtxs SF FE ->
      NS : names_same EE SG ->
      Ev : evalExpr FE EE E V EE' O ->
      Lev : level SF SG PC E L ->
      NEq : (PC = public -> false) ->
      O = []
  on Ev as IH_E,
  args_not_public_no_output :
    forall A SF SG PC L FE EE V EE' O,
      IsA : is_args A ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      SFC : secFunCtxs SF FE ->
      NS : names_same EE SG ->
      Ev : evalArgs FE EE A V EE' O ->
      Lev : levelArgs SF SG PC A L ->
      NEq : (PC = public -> false) ->
      O = []
  on Ev as IH_A,
  recFields_not_public_no_output :
    forall RF SF SG PC L FE EE V EE' O,
      IsRF : is_recFieldExprs RF ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE : is_list (is_list (is_pair is_string is_value)) EE ->
      SFC : secFunCtxs SF FE ->
      NS : names_same EE SG ->
      Ev : evalRecFields FE EE RF V EE' O ->
      Lev : levelRecFields SF SG PC RF L ->
      NEq : (PC = public -> false) ->
      O = []
  on Ev as IH_RF. [Show Proof]



Extensible_Theorem
  secure_output : forall S SF SG PC SG' FE ScopeA EE_A EE_A' OA
                       ScopeB EE_B EE_B' OB,
    IsS : is_stmt S ->
    IsSF : is_list (is_pair is_string
                   (is_pair is_slev (is_list is_slev))) SF ->
    IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
    IsPC : is_slev PC ->
    IsFE : is_list (is_pair is_string
                   (is_pair is_string
                   (is_pair is_value
                   (is_pair (is_list is_string) is_stmt)))) FE ->
    IsEE_A : is_list (is_list (is_pair is_string is_value))
                (ScopeA::EE_A) ->
    IsEE_B : is_list (is_list (is_pair is_string is_value))
                (ScopeB::EE_B) ->
    SFC : secFunCtxs SF FE ->
    NSA : names_same (ScopeA::EE_A) SG ->
    NSB : names_same (ScopeB::EE_B) SG ->
    PE : public_equiv SG (ScopeA::EE_A) (ScopeB::EE_B) ->
    Sec : secure SF SG PC S SG' ->
    EvA : evalStmt FE (ScopeA::EE_A) S EE_A' OA ->
    EvB : evalStmt FE (ScopeB::EE_B) S EE_B' OB ->
    OA = OB
  on EvA as IH_S,
  expr_secure_output :
    forall E SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsE : is_expr E ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : level SF SG PC E L ->
      EvA : evalExpr FE EE_A E VA EE_A' OA ->
      EvB : evalExpr FE EE_B E VB EE_B' OB ->
      OA = OB
  on EvA as IH_E,
  args_secure_output :
    forall A SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsA : is_args A ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelArgs SF SG PC A L ->
      EvA : evalArgs FE EE_A A VA EE_A' OA ->
      EvB : evalArgs FE EE_B A VB EE_B' OB ->
      OA = OB
  on EvA as IH_A,
  recFields_secure_output :
    forall RF SF SG PC L FE EE_A EE_A' VA OA EE_B EE_B' VB OB,
      IsRF : is_recFieldExprs RF ->
      IsSF : is_list (is_pair is_string
                     (is_pair is_slev (is_list is_slev))) SF ->
      IsSG : is_list (is_list (is_pair is_string is_slev)) SG ->
      IsPC : is_slev PC ->
      IsFE : is_list (is_pair is_string
                     (is_pair is_string
                     (is_pair is_value
                     (is_pair (is_list is_string) is_stmt)))) FE ->
      IsEE_A : is_list (is_list (is_pair is_string is_value)) EE_A ->
      IsEE_B : is_list (is_list (is_pair is_string is_value)) EE_B ->
      SFC : secFunCtxs SF FE ->
      NSA : names_same EE_A SG ->
      NSB : names_same EE_B SG ->
      PE : public_equiv SG EE_A EE_B ->
      Lev : levelRecFields SF SG PC RF L ->
      EvA : evalRecFields FE EE_A RF VA EE_A' OA ->
      EvB : evalRecFields FE EE_B RF VB EE_B' OB ->
      OA = OB
  on EvA as IH_RF. [Show Proof]





/********************************************************************
 Programs do not leak private information
 ********************************************************************/
%--------------------------------------------
% Everything gathered has is relations
%--------------------------------------------
Extensible_Theorem
  paramSec_is : forall P Name L,
    IsP : is_param P ->
    PS : paramSec P Name L ->
    is_string Name /\ is_slev L
  on PS. [Show Proof]


Theorem paramSecs_is : forall Ps PSecs,
  is_list is_param Ps -> paramSecs Ps PSecs ->
  is_list (is_pair is_string is_slev) PSecs. [Show Proof]


Theorem values_is_sec : forall L V,
  is_list (is_pair is_string is_slev) L -> values L V ->
  is_list is_slev V. [Show Proof]


Extensible_Theorem
  getFunSec_is : forall F Name RetLev PSecs,
    IsF : is_fun F ->
    GFS : getFunSec F Name RetLev PSecs ->
    is_string Name /\ is_slev RetLev /\ is_list is_slev PSecs
  on GFS. [Show Proof]


Theorem gatherFunSecCtx_is : forall Fs SF,
  is_list is_fun Fs -> gatherFunSecCtx Fs SF ->
  is_list (is_pair is_string (is_pair is_slev (is_list is_slev))) SF. [Show Proof]


Extensible_Theorem
  program_secure_is : forall P S,
    IsP : is_program P ->
    Sec : programSecure P S ->
    is_list is_slev S
  on Sec. [Show Proof]



%--------------------------------------------
% Everything gathered is unique
%--------------------------------------------
Extensible_Theorem
  paramSec_unique : forall P NameA LA NameB LB,
    IsP : is_param P ->
    PSA : paramSec P NameA LA ->
    PSB : paramSec P NameB LB ->
    NameA = NameB /\ LA = LB
  on PSA. [Show Proof]


Theorem paramSecs_unique : forall Ps PSecsA PSecsB,
  is_list is_param Ps -> paramSecs Ps PSecsA -> paramSecs Ps PSecsB ->
  PSecsA = PSecsB. [Show Proof]


Extensible_Theorem
  getFunSec_unique : forall F NA LA PSA NB LB PSB,
    IsF : is_fun F ->
    GFSA : getFunSec F NA LA PSA ->
    GFSB : getFunSec F NB LB PSB ->
    NA = NB /\ LA = LB /\ PSA = PSB
  on GFSA. [Show Proof]


Theorem gatherFunSecCtx_unique : forall Fs SFA SFB,
  is_list is_fun Fs -> gatherFunSecCtx Fs SFA ->
  gatherFunSecCtx Fs SFB -> SFA = SFB. [Show Proof]


Extensible_Theorem
  program_secure_unique : forall P A B,
    IsP : is_program P ->
    SecA : programSecure P A ->
    SecB : programSecure P B ->
    A = B
  on SecA. [Show Proof]



%--------------------------------------------
% Gathered security and eval info are related
%--------------------------------------------
Extensible_Theorem
  paramName_paramSec : forall P N NS L,
    IsP : is_param P ->
    PN : paramName P N ->
    PS : paramSec P NS L ->
    N = NS
  on PS. [Show Proof]


Theorem paramNames_paramSecs : forall Ps PNs PSecs,
  is_list is_param Ps -> paramNames Ps PNs -> paramSecs Ps PSecs ->
  domain PSecs PNs. [Show Proof]


Theorem domain_values_zip[A, B] : forall (L : list (pair A B)) D V,
  domain L D -> values L V -> zip D V L. [Show Proof]


Extensible_Theorem
  getFun_sec :
    forall F FName RetVar RVVal PNames Body SName RetLev PSecs SF,
      IsF : is_fun F ->
      GFEI : getFunEvalInfo F FName RetVar RVVal PNames Body ->
      GFS : getFunSec F SName RetLev PSecs ->
      FS : funSecure SF F ->
      exists ZP SG, FName = SName /\
                    zip PNames PSecs ZP /\
                    secure SF [(RetVar, RetLev)::ZP] RetLev Body SG
  on GFS. [Show Proof]


%can't do secFunCtxs directly due to need to use SF_Full,
%   but this lets us build it
Theorem gatherCtxs_secFunCtxs :
  forall Fs SF FE SF_Full FName RetLev PSecs RetVar RVVal PNames Body,
    is_list is_fun Fs -> gatherFunSecCtx Fs SF ->
    getFunEvalCtx Fs FE -> funsSecure SF_Full Fs ->
    lookup SF FName (RetLev, PSecs) ->
    lookup FE FName (RetVar, RVVal, PNames, Body) ->
    exists ZP SG, zip PNames PSecs ZP /\
       secure SF_Full [(RetVar, RetLev)::ZP] RetLev Body SG. [Show Proof]



%--------------------------------------------
% Secure programs do not leak in output
%--------------------------------------------
Extensible_Theorem
  program_secure : forall P A_S A_A A_B O_A O_B,
    IsP : is_program P ->
    IsA_A : is_list is_value A_A ->
    IsA_B : is_list is_value A_B ->
    Sec : programSecure P A_S ->
    %different sets of arguments to main have the same public args,
    %   but may differ in private args
    Rel : level_arg_vals A_S A_A A_B ->
    EvA : evalProgram A_A P O_A ->
    EvB : evalProgram A_B P O_B ->
    O_A = O_B
  on Sec. [Show Proof]



/*
  We frame program security as having the same output if the public
  arguments to main are the same.  The concept of non-public arguments
  to main sounds a bit strange; isn't the user, the person from whom
  we are hiding private information, giving all the arguments?  We can
  think of private arguments as standing in for the contents of files
  and such, so a private argument might be an encryption key for the
  program read from the file.  Therefore it does make sense to have
  non-public arguments to main.
*/

/*
  The security extension as written isn't very useful.  Suppose we
  want to write a password checker, a good use for information flow
  security, using it.  We take the true password and a user's attempt
  as arguments to main, compare them, and find we cannot output
  whether they matched because the true password is private, and thus
  the result of comparing them is also private and cannot be printed.

  A "real" version of this extension, intended to be used for writing
  real programs, would need a declassify construct to lower
  information to a public level.  Such a construct is unsound for
  security, which is why we don't include it here where we are
  concerned with proving soundness, not writing actual programs.
  However, it allows a programmer to decide explicitly what private
  information may escape and in what circumstances, so it is
  effectively good enough.  For example, telling the user the
  passwords matched or didn't leaks a little bit of information to the
  user about the true password, but the programmer decides this is
  still secure enough and necessary for the job the program is doing.
*/

Back to example home