oadt.lang_oadt.syntax

From oadt Require Import lang_oadt.base.

Implicit Types (b : ) (x X y Y : atom) (L : aset).

Definitions

Expressions (e, Ļ„)

This corresponds to expressions in Fig. 9 in the paper. Here we use locally nameless representation for binders.
Inductive expr :=
(* Locally bound variables, i.e. de Bruijn indices. *)
| EBVar (k : )
(* Free variables *)
| EFVar (x : atom)
(* Global variables, referring to global functions, ADTs and OADTs. *)
| EGVar (x : atom)
(* Simple types *)
| EUnitT
(* Oblivious Boolean if the label is high, otherwise public Boolean *)
| EBool (l : )
| EProd ( : expr)
(* Oblivious sum if the label is high, otherwise public sum *)
| ESum (l : ) ( : expr)
(* Dependent function type *)
| EPi ( : expr)
(* Unit and Boolean values *)
| EUnitV
| ELit (b : )
(* Function abstraction *)
| EAbs (Ļ„ e : expr)
(* Expression and type application *)
| EApp ( : expr)
(* Let binding *)
| ELet ( : expr)
(* Oblivious conditional (i.e. MUX) if the label is high, otherwise public
conditional *)

| EIte (l : ) ( : expr)
(* Pair and projection *)
| EPair ( : expr)
| EProj (b : ) (e : expr)
(* Oblivious injection if the label is high, otherwise public injection *)
| EInj (l : ) (b : ) (Ļ„ e : expr)
(* Oblivious sum elimination if the label is high, otherwise public sum
elimination *)

| ECase (l : ) ( : expr) ( : expr) ( : expr)
(* Iso-recursive type introduction and elimination *)
| EFold (X : atom) (e : expr)
| EUnfold (X : atom) (e : expr)
(* Section for Boolean *)
| ESec (e : expr)
(* Runtime boxed values *)
| EBoxedLit (b : )
| EBoxedInj (b : ) (Ļ„ e : expr)
.

Global definitions (D)

This corresponds to global definitions in Fig. 9 in the paper.
Variant gdef :=
| DADT (e : expr)
| DFun (Ļ„ e : expr)
| DOADT (Ļ„ e : expr)
.

Global context (Ī£)

A store of global definitions.
Notation gctx := (amap gdef).

Programs (P)

Notation program := (gctx * expr).

Notations for expressions

Module expr_notations.

(* Adapted from _Software Foundations_. *)
Coercion ELit : bool >-> expr.
Coercion EBVar : nat >-> expr.

Quote
Notation "<{ e }>" := e (e custom oadt at level 99).
Lispy unquote
Notation "',(' e ')'" := e (in custom oadt at level 0,
                               e constr at level 0).

Notation "'high'" := (true) (only parsing).
Notation "'low'" := (false) (only parsing).

Notation "( x )" := x (in custom oadt, x at level 99).
Notation "x" := x (in custom oadt at level 0, x constr at level 0).
Notation "'bvar' x" := (EBVar x) (in custom oadt at level 0, x constr at level 0,
                                     only parsing).
Notation "'fvar' x" := (EFVar x) (in custom oadt at level 0, x constr at level 0,
                                     only parsing).
Notation "'gvar' x" := (EGVar x) (in custom oadt at level 0, x constr at level 0).
Notation "'lit' b" := (ELit b) (in custom oadt at level 0, b constr at level 0,
                                   only parsing).
Notation "'šŸ™'" := EUnitT (in custom oadt at level 0).
Notation "'Unit'" := EUnitT (in custom oadt at level 0, only parsing).
Notation "'š”¹{' l '}'" := (EBool l) (in custom oadt at level 0,
                                       l constr at level 0,
                                       format "'š”¹{' l '}'").
Notation "'š”¹'" := (EBool low) (in custom oadt at level 0).
Notation "'Bool'" := (EBool low) (in custom oadt at level 0, only parsing).
Notation "'~š”¹'" := (EBool high) (in custom oadt at level 0).
Notation "'~Bool'" := (EBool high) (in custom oadt at level 0, only parsing).
Notation "τ1 * τ2" := (EProd τ1 τ2) (in custom oadt at level 2,
                                        Ļ„1 custom oadt,
                                        Ļ„2 custom oadt at level 0).
Notation "τ1 '+{' l '}' τ2" := (ESum l τ1 τ2) (in custom oadt at level 3,
                                                  l constr at level 0,
                                                  left associativity,
                                                  format "Ļ„1 '+{' l '}' Ļ„2").
Notation "τ1 + τ2" := (ESum low τ1 τ2) (in custom oadt at level 3,
                                           left associativity).
Notation "τ1 ~+ τ2" := (ESum high τ1 τ2) (in custom oadt at level 3,
                                             left associativity).
Notation "'Π' : τ1 , τ2" := (EPi τ1 τ2) (in custom oadt at level 50,
                                            right associativity,
                                            format "Ī  : Ļ„1 , Ļ„2").
Notation "\ : Ļ„ '=>' e" := (EAbs Ļ„ e) (in custom oadt at level 90,
                                          Ļ„ custom oadt at level 99,
                                          e custom oadt at level 99,
                                          left associativity,
                                          format "\ : Ļ„ => e").
Notation "e1 e2" := (EApp ) (in custom oadt at level 1, left associativity).
Notation "()" := EUnitV (in custom oadt at level 0).
Notation "( x , y , .. , z )" := (EPair .. (EPair x y) .. z)
                                   (in custom oadt at level 0,
                                       x custom oadt at level 99,
                                       y custom oadt at level 99,
                                       z custom oadt at level 99).
Notation "'Ļ€@' b e" := (EProj b e) (in custom oadt at level 0,
                                       b constr at level 0,
                                       e custom oadt at level 0,
                                       format "Ļ€@ b e").
Notation "'Ļ€1' e" := (EProj true e) (in custom oadt at level 0,
                                        e custom oadt at level 0).
Notation "'Ļ€2' e" := (EProj false e) (in custom oadt at level 0,
                                         e custom oadt at level 0).
Notation "'sš”¹' e" := (ESec e) (in custom oadt at level 0,
                                  e custom oadt at level 0).
Notation "'if{' l '}' e0 'then' e1 'else' e2" := (EIte l )
                                                   (in custom oadt at level 89,
                                                       l constr at level 0,
                                                        custom oadt at level 99,
                                                        custom oadt at level 99,
                                                        custom oadt at level 99,
                                                       left associativity,
                                                       format "'if{' l '}' e0 'then' e1 'else' e2").
Notation "'if' e0 'then' e1 'else' e2" := (EIte low )
                                            (in custom oadt at level 89,
                                                 custom oadt at level 99,
                                                 custom oadt at level 99,
                                                 custom oadt at level 99,
                                                left associativity).
Notation "'~if' e0 'then' e1 'else' e2" := (EIte high )
                                             (in custom oadt at level 89,
                                                  custom oadt at level 99,
                                                  custom oadt at level 99,
                                                  custom oadt at level 99).
Notation "'let' e1 'in' e2" := (ELet )
                                 (in custom oadt at level 0,
                                      custom oadt at level 99,
                                      custom oadt at level 99).
Notation "'inj{' l '}@' b < Ļ„ > e" := (EInj l b Ļ„ e) (in custom oadt at level 0,
                                                         l constr at level 0,
                                                         b constr at level 0,
                                                         Ļ„ custom oadt at level 0,
                                                         e custom oadt at level 0,
                                                         format "'inj{' l '}@' b < Ļ„ > e").
Notation "'inj@' b < Ļ„ > e" := (EInj low b Ļ„ e) (in custom oadt at level 0,
                                                    b constr at level 0,
                                                    Ļ„ custom oadt at level 0,
                                                    e custom oadt at level 0,
                                                    format "inj@ b < Ļ„ > e").
Notation "'inl' < Ļ„ > e" := (EInj low true Ļ„ e) (in custom oadt at level 0,
                                                    Ļ„ custom oadt at level 0,
                                                    e custom oadt at level 0,
                                                    format "inl < Ļ„ > e").
Notation "'inr' < Ļ„ > e" := (EInj low false Ļ„ e) (in custom oadt at level 0,
                                                     Ļ„ custom oadt at level 0,
                                                     e custom oadt at level 0,
                                                     format "inr < Ļ„ > e").
Notation "'~inj@' b < Ļ„ > e" := (EInj high b Ļ„ e) (in custom oadt at level 0,
                                                      b constr at level 0,
                                                      Ļ„ custom oadt at level 0,
                                                      e custom oadt at level 0,
                                                      format "~inj@ b < Ļ„ > e").
Notation "'~inl' < Ļ„ > e" := (EInj high true Ļ„ e) (in custom oadt at level 0,
                                                      Ļ„ custom oadt at level 0,
                                                      e custom oadt at level 0,
                                                      format "~inl < Ļ„ > e").
Notation "'~inr' < Ļ„ > e" := (EInj high false Ļ„ e) (in custom oadt at level 0,
                                                       Ļ„ custom oadt at level 0,
                                                       e custom oadt at level 0,
                                                       format "~inr < Ļ„ > e").
(* I still want to use high and low *)
Notation "'case{' l '}' e0 'of' e1 '|' e2" :=
  (ECase l ) (in custom oadt at level 89,
                         l constr at level 0,
                          custom oadt at level 99,
                          custom oadt at level 99,
                          custom oadt at level 99,
                         left associativity,
                         format "'case{' l '}' e0 'of' e1 '|' e2").
Notation "'case' e0 'of' e1 '|' e2" :=
  (ECase low ) (in custom oadt at level 89,
                            custom oadt at level 99,
                            custom oadt at level 99,
                            custom oadt at level 99,
                           left associativity).
Notation "'~case' e0 'of' e1 '|' e2" :=
  (ECase high ) (in custom oadt at level 89,
                             custom oadt at level 99,
                             custom oadt at level 99,
                             custom oadt at level 99,
                            left associativity).
Notation "'fold' < X > e" := (EFold X e) (in custom oadt at level 0,
                                             X custom oadt at level 0,
                                             e custom oadt at level 0,
                                             format "fold < X > e").
Notation "'unfold' < X > e" := (EUnfold X e) (in custom oadt at level 0,
                                                 X custom oadt at level 0,
                                                 e custom oadt at level 0,
                                                 format "unfold < X > e").
Notation "[ b ]" := (EBoxedLit b) (in custom oadt at level 0,
                                      b constr at level 0).
Notation "[ 'inj@' b < Ļ„ > e ]" := (EBoxedInj b Ļ„ e)
                                     (in custom oadt at level 0,
                                         b constr at level 0,
                                         Ļ„ custom oadt at level 0,
                                         e custom oadt at level 0,
                                         format "[ inj@ b < Ļ„ > e ]").
Notation "[ 'inl' < Ļ„ > e ]" := (EBoxedInj true Ļ„ e)
                                  (in custom oadt at level 0,
                                      Ļ„ custom oadt at level 0,
                                      e custom oadt at level 0,
                                      format "[ inl < Ļ„ > e ]").
Notation "[ 'inr' < Ļ„ > e ]" := (EBoxedInj false Ļ„ e)
                                  (in custom oadt at level 0,
                                      Ļ„ custom oadt at level 0,
                                      e custom oadt at level 0,
                                      format "[ inr < Ļ„ > e ]").

Notation "D" := D (in custom oadt_def at level 0, D constr at level 0).
Notation "( D )" := D (in custom oadt_def, D at level 99).
Notation "'data' X := e" := (X, DADT e) (in custom oadt_def at level 0,
                                            X constr at level 0,
                                            e custom oadt at level 99).
Notation "'obliv' X ( : Ļ„ ) := e" := (X, DOADT Ļ„ e)
                                       (in custom oadt_def at level 0,
                                           X constr at level 0,
                                           Ļ„ custom oadt at level 99,
                                           e custom oadt at level 99,
                                           format "obliv X ( : Ļ„ ) := e").
Notation "'def' x : Ļ„ := e" := (x, DFun Ļ„ e) (in custom oadt_def at level 0,
                                                 x constr at level 0,
                                                 Ļ„ custom oadt at level 99,
                                                 e custom oadt at level 99).
Notation "[{ x }]" := (cons x nil)
                        (x custom oadt_def at level 99).
Notation "[{ x ; y ; .. ; z }]" := (cons x (cons y .. (cons z nil) ..))
                                     (x custom oadt_def at level 99,
                                      y custom oadt_def at level 99,
                                      z custom oadt_def at level 99,
                                      format "[{ '[v ' '/' x ; '/' y ; '/' .. ; '/' z ']' '//' }]").

Notation "'ite' e0 e1 e2" := (if then else )
                               (in custom oadt at level 0,
                                    constr at level 0,
                                    custom oadt at level 0,
                                    custom oadt at level 0).

End expr_notations.

More Definitions

Section definitions.

Import expr_notations.
#[local]
Coercion EFVar : atom >-> expr.

Indistinguishability

This corresponds to Definition 3.6 (Indistinguishability) in the paper. Instead of formalizing an observe function and considering two expressions indistinguishable if they are observed the same, we directly formalize the indistinguishability relation as the equivalence induced by the observe function.
All rules but the rules for boxed expressions are just congruence rules. Some rules are not necessary if the expressions are well-typed, but we include them anyway.
Reserved Notation "e 'ā‰ˆ' e'" (at level 40).

Inductive indistinguishable : expr -> expr -> Prop :=
| IBVar k : <{ bvar k }> ā‰ˆ <{ bvar k }>
| IFVar x : <{ fvar x }> ā‰ˆ <{ fvar x }>
| IGVar x : <{ gvar x }> ā‰ˆ <{ gvar x }>
| IPi :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ Ī :, }> ā‰ˆ <{ Ī :, }>
| IAbs Ļ„ Ļ„' e e' :
    Ļ„ ā‰ˆ Ļ„' ->
    e ā‰ˆ e' ->
    <{ \:Ļ„ => e }> ā‰ˆ <{ \:Ļ„' => e' }>
| ILet :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ let in }> ā‰ˆ <{ let in }>
| ICase l :
     ā‰ˆ ->
     ā‰ˆ ->
     ā‰ˆ ->
    <{ case{l} of | }> ā‰ˆ <{ case{l} of | }>
| IUnitT : <{ šŸ™ }> ā‰ˆ <{ šŸ™ }>
| IBool l : <{ š”¹{l} }> ā‰ˆ <{ š”¹{l} }>
| IProd :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ * }> ā‰ˆ <{ * }>
| ISum l :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ +{l} }> ā‰ˆ <{ +{l} }>
| IApp :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ }> ā‰ˆ <{ }>
| IUnitV : <{ () }> ā‰ˆ <{ () }>
| ILit b : <{ lit b }> ā‰ˆ <{ lit b }>
| ISec e e' :
    e ā‰ˆ e' ->
    <{ sš”¹ e }> ā‰ˆ <{ sš”¹ e' }>
| IIte l :
     ā‰ˆ ->
     ā‰ˆ ->
     ā‰ˆ ->
    <{ if{l} then else }> ā‰ˆ <{ if{l} then else }>
| IPair :
     ā‰ˆ ->
     ā‰ˆ ->
    <{ (, ) }> ā‰ˆ <{ (, ) }>
| IProj b e e' :
    e ā‰ˆ e' ->
    <{ Ļ€@b e }> ā‰ˆ <{ Ļ€@b e' }>
| IInj l b Ļ„ Ļ„' e e' :
    Ļ„ ā‰ˆ Ļ„' ->
    e ā‰ˆ e' ->
    <{ inj{l}@b<Ļ„> e }> ā‰ˆ <{ inj{l}@b<Ļ„'> e' }>
| IFold X e e' :
    e ā‰ˆ e' ->
    <{ fold<X> e }> ā‰ˆ <{ fold<X> e' }>
| IUnfold X e e' :
    e ā‰ˆ e' ->
    <{ unfold<X> e }> ā‰ˆ <{ unfold<X> e' }>
(* The only interesting cases *)
| IBoxedLit b b' :
    (* We can not distinguish between two encrypted boolean values. *)
    <{ [b] }> ā‰ˆ <{ [b'] }>
| IBoxedInj b b' Ļ„ e e' :
    (* We can not tell which branch an encrypted sum injects to nor what the
    encrypted value is. But the type information is public so we need to make
    sure nothing leaked from this type information. Technically we only need the
    two types to be indistinguishable, but the stronger notion of equality also
    works. *)

    <{ [inj@b<Ļ„> e] }> ā‰ˆ <{ [inj@b'<Ļ„> e'] }>

where "e 'ā‰ˆ' e'" := (indistinguishable e e').

Variable opening

Reserved Notation "'{' k '~>' s '}' e" (in custom oadt at level 20, k constr).

Fixpoint open_ (k : ) (s : expr) (e : expr) : expr :=
  match e with
  | <{ bvar n }> => if decide (k = n) then s else e
  | <{ Ī :Ļ„1, Ļ„2 }> => <{ Ī :{k~>s}Ļ„1, {S k~>s}Ļ„2 }>
  | <{ \:Ļ„ => e }> => <{ \:{k~>s}Ļ„ => {S k~>s}e }>
  | <{ let in }> => <{ let {k~>s} in {S k~>s} }>
  | <{ case{l} of | }> => <{ case{l} {k~>s} of {S k~>s} | {S k~>s} }>
  (* Congruence rules *)
  | <{ Ļ„1 * Ļ„2 }> => <{ ({k~>s}Ļ„1) * ({k~>s}Ļ„2) }>
  | <{ Ļ„1 +{l} Ļ„2 }> => <{ ({k~>s}Ļ„1) +{l} ({k~>s}Ļ„2) }>
  | <{ }> => <{ ({k~>s}) ({k~>s}) }>
  | <{ sš”¹ e }> => <{ sš”¹ ({k~>s}e) }>
  | <{ if{l} then else }> => <{ if{l} {k~>s} then {k~>s} else {k~>s} }>
  | <{ (, ) }> => <{ ({k~>s}, {k~>s}) }>
  | <{ Ļ€@b e }> => <{ Ļ€@b ({k~>s}e) }>
  | <{ inj{l}@b<Ļ„> e }> => <{ inj{l}@b<({k~>s}Ļ„)> ({k~>s}e) }>
  | <{ fold<X> e }> => <{ fold<X> ({k~>s}e) }>
  | <{ unfold<X> e }> => <{ unfold<X> ({k~>s}e) }>
  | _ => e
  end

where "'{' k '~>' s '}' e" := (open_ k s e) (in custom oadt).

Definition open s e := open_ 0 s e.
Notation "e ^ s" := (open s e) (in custom oadt at level 20).

Substitution

Reserved Notation "'{' x '↦' s '}' e" (in custom oadt at level 20, x constr).

Fixpoint subst (x : atom) (s : expr) (e : expr) : expr :=
  match e with
  | <{ fvar y }> => if decide (x = y) then s else e
  (* Congruence rules *)
  | <{ Ī :Ļ„1, Ļ„2 }> => <{ Ī :{x↦s}Ļ„1, {x↦s}Ļ„2 }>
  | <{ \:Ļ„ => e }> => <{ \:{x↦s}Ļ„ => {x↦s}e }>
  | <{ let in }> => <{ let {x↦s} in {x↦s} }>
  | <{ case{l} of | }> => <{ case{l} {x↦s} of {x↦s} | {x↦s} }>
  | <{ Ļ„1 * Ļ„2 }> => <{ ({x↦s}Ļ„1) * ({x↦s}Ļ„2) }>
  | <{ Ļ„1 +{l} Ļ„2 }> => <{ ({x↦s}Ļ„1) +{l} ({x↦s}Ļ„2) }>
  | <{ }> => <{ ({x↦s}) ({x↦s}) }>
  | <{ sš”¹ e }> => <{ sš”¹ ({x↦s}e) }>
  | <{ if{l} then else }> => <{ if{l} {x↦s} then {x↦s} else {x↦s} }>
  | <{ (, ) }> => <{ ({x↦s}, {x↦s}) }>
  | <{ Ļ€@b e }> => <{ Ļ€@b ({x↦s}e) }>
  | <{ inj{l}@b<Ļ„> e }> => <{ inj{l}@b<({x↦s}Ļ„)> ({x↦s}e) }>
  | <{ fold<X> e }> => <{ fold<X> ({x↦s}e) }>
  | <{ unfold<X> e }> => <{ unfold<X> ({x↦s}e) }>
  | _ => e
  end

where "'{' x '↦' s '}' e" := (subst x s e) (in custom oadt).

Oblivious type values (ω)

This corresponds to oblivious type values in Fig. 9 in the paper.

Oblivious values (v)

This corresponds to oblivious values in Fig. 9 in the paper.

Values (v)

This corresponds to values in Fig. 9 in the paper.

Local closure and well-formedness of expressions

Inductive lc : expr -> Prop :=
| LCFVar x : lc <{ fvar x }>
| LCGVar x : lc <{ gvar x }>
| LCPi L :
    ( x, x āˆ‰ L -> lc <{ ^x }>) ->
    lc -> lc <{ Ī :, }>
| LCAbs Ļ„ e L :
    ( x, x āˆ‰ L -> lc <{ e^x }>) ->
    lc Ļ„ -> lc <{ \:Ļ„ => e }>
| LCLet L :
    ( x, x āˆ‰ L -> lc <{ ^x }>) ->
    lc -> lc <{ let in }>
| LCCase l :
    ( x, x āˆ‰ -> lc <{ ^x }>) ->
    ( x, x āˆ‰ -> lc <{ ^x }>) ->
    lc -> lc <{ case{l} of | }>
(* Congruence rules *)
| LCUnitT : lc <{ šŸ™ }>
| LCBool l : lc <{ š”¹{l} }>
| LCProd : lc -> lc -> lc <{ * }>
| LCSum l : lc -> lc -> lc <{ +{l} }>
| LCApp : lc -> lc -> lc <{ }>
| LCUnitV : lc <{ () }>
| LCLit b : lc <{ lit b }>
| LCSec e : lc e -> lc <{ sš”¹ e }>
| LCIte l : lc -> lc -> lc -> lc <{ if{l} then else }>
| LCPair : lc -> lc -> lc <{ (, ) }>
| LCProj b e : lc e -> lc <{ π@b e }>
| LCInj l b Ļ„ e : lc Ļ„ -> lc e -> lc <{ inj{l}@b<Ļ„> e }>
| LCFold X e : lc e -> lc <{ fold<X> e }>
| LCUnfold X e : lc e -> lc <{ unfold<X> e }>
| LCBoxedLit b : lc <{ [b] }>
(* Techincally this is not only locally closed, but more about
well-formedness. *)

| LCBoxedInj b ω v : otval ω -> oval v -> lc <{ [inj@b<ω> v] }>
.

End definitions.

Notations

Module notations.

Export expr_notations.

Notation "e 'ā‰ˆ' e'" := (indistinguishable e e') (at level 40).

Notation "'{' k '~>' s '}' e" := (open_ k s e)
                                   (in custom oadt at level 20, k constr).
Notation "e ^ s" := (open s e) (in custom oadt at level 20).

Notation "'{' x '↦' s '}' e" := (subst x s e)
                                  (in custom oadt at level 20, x constr).
Notation "{ x '↦' s }" := (subst x s) (at level 20).

Notation "x # s" := (x āˆ‰ stale s) (at level 40).

End notations.