Compiler Optimisations: Security-Preserving Refinement (NuSMV)¶
Description of the Case Study¶
We study three compiler optimisation patterns and analyse whether they preserve the security guarantees of the original program. Each optimisation transforms a loop-based routine into a more efficient variant: Loop Peeling (LP) moves one iteration outside the loop, Expression Folding Loop Peeling (EFLP) normalises arithmetic expressions, and Dead Branch Elimination (DBE) removes infeasible public branches. For every pair, the source model captures the original program and the target model implements the optimised version. The HyperLTL specification requires that public outputs remain indistinguishable across both programs, ensuring that the transformation does not introduce information leaks.
The NuSMV model(s)¶
MODULE main
VAR
step: 0..9;
int_x: 0..15;
int_k: 0..3;
in_secret: 0..3;
out_public: 0..3;
ASSIGN
-- D = 32
-- L0:
-- L1: x = 0
-- L2: k = 0
-- L3: while (k < 3) {
-- L4: if (k == 0) {
-- L5: x := in_secretput();}
-- L6: else {x := x + x;}
-- L7: k := k + 1;
-- L8: out_publicput(x % k);
-- L9: END
init(step):= 0;
next(step):=
case
(step=0): {1};
(step=1): {2};
(step=2): {3};
((step=3) & (int_k<3)): {4};
((step=3) & !(int_k<3)): {9};
((step=4) & (int_k=0)): {5};
((step=4) & !(int_k=0)): {6};
(step=5): {7};
(step=6): {7};
(step=7): {8};
(step=8): {3};
(step=9): {9};
TRUE: step;
esac;
init(int_x) := 0;
next(int_x) :=
case
-- ((int_x+int_x)>15): 15;
(int_x > 7): 15;
(step=5) : in_secret;
(step=6) : (int_x + int_x);
TRUE: int_x;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=7) : int_k + 1;
TRUE: int_k;
esac;
init(out_public) := 0;
next(out_public) :=
case
((step=8)& !(int_k=0)): (int_x mod int_k);
TRUE: out_public;
esac;
init(in_secret) := {0, 1, 2, 3};
next(in_secret) := in_secret;
DEFINE
halt := (step=9);
MODULE main
VAR
step: 0..14;
int_x: 0..15;
int_k: 0..3;
in_secret: 0..3;
out_public: 0..3;
ASSIGN
-- L0:
-- L1: x = 0
-- L2: k = 0
-- L3: if (k == 0)
-- L4: {x := in_secretput();}
-- L5: else {x := x + x;}
-- L6: k := k + 1;
-- L7: out_publicput = (x % k);
-- L8: while (k < 3) {
-- L9: if (k == 0) {
-- L10: x := in_secretput();}
-- L11: else {x := x + x;}
-- L12: k := k + 1;
-- L13: out_publicput(x % k);
-- L14: END
init(step):= 0;
next(step):=
case
(step=0): {1};
(step=1): {2};
(step=2): {3};
((step=3) & (int_k=0)): {4};
((step=3) & !(int_k=0)): {5};
(step=4): {6};
(step=5): {6};
(step=6): {7};
(step=7): {8};
((step=8) & (int_k<3)): {9};
((step=8) & !(int_k<3)): {14};
((step=9) & (int_k=0)): {10};
((step=9) & !(int_k=0)): {11};
(step=10): {12};
(step=11): {12};
(step=12): {13};
(step=13): {8};
(step=14): {14};
TRUE: step;
esac;
init(int_x) := 0;
next(int_x) :=
case
(int_x > 7): 15;
(step=4) : in_secret;
(step=5) : (int_x + int_x);
(step=10) : in_secret;
(step=11) : (int_x + int_x);
TRUE: int_x;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=6) : int_k+1;
(step=12) : int_k+1;
TRUE: int_k;
esac;
init(out_public) := 0;
next(out_public) :=
case
((step=7)& !(int_k=0)): (int_x mod int_k);
((step=13)& !(int_k=0)): (int_x mod int_k);
TRUE: out_public;
esac;
init(in_secret) := {0, 1, 2, 3};
next(in_secret) := in_secret;
DEFINE
halt := (step=14);
MODULE main
VAR
step: 0..6;
in_int_x: 0..9;
in_int_y: 0..3;
secret: 0..9;
int_k: 0..3;
obs_public_out: 0..3;
ASSIGN
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: while (k < 3) {
-- L1: if (k == 0 || k == y) {
-- L2: x := secretput();}
-- L3: else {x := x + x;}
-- L4: k := k + 1;
-- L5: obs_public_output(x % k);
-- L6: END
init(step):= 0;
next(step):=
case
((step=0) & (int_k<3)): {1};
((step=0) & !(int_k<3)): {6};
((step=1) & ((int_k=0) | (int_k=in_int_y))): {2};
((step=1) & !((int_k=0) | (int_k=in_int_y))): {3};
(step=2): {4};
(step=3): {4};
(step=4): {5};
(step=5): {0};
(step=6): {6};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
-- ((in_int_x+in_int_x)>9): 9;
(in_int_x>4): 9;
(step=2) : secret;
(step=3) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=5) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=4) : int_k+1;
TRUE: int_k;
esac;
init(secret) := 0;
next(secret) :=
case
(step=1) : {0,1,2,3};
TRUE: secret;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=5)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=6);
MODULE main
VAR
step: 0..12;
in_int_x: 0..9;
in_int_y: 0..3;
int_k: 0..3;
secret: 0..9;
obs_public_out: 0..3;
ASSIGN
-- L0:
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: if (k == 0 || k == y)
-- L1: {x := in_secretput();}
-- L2: else {x := x + x;}
-- L3: k := k + 1;
-- L4: obs_public_output = (x % k);
-- L5: while (k < 3) {
-- L6: y = input()
-- L7: if (k == 0 || k == y) {
-- L8: x := in_secretput();}
-- L9: else {x := x + x;}
-- L10: k := k + 1;
-- L11: obs_public_output(x % k);
-- L12: END
init(step):= 0;
next(step):=
case
((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
(step=1): {3};
(step=2): {3};
(step=3): {4};
(step=4): {5};
((step=5) & (int_k<3)): {6};
((step=5) & !(int_k<3)): {11};
((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
(step=7): {9};
(step=8): {9};
(step=9): {10};
(step=10): {5};
(step=11): {11};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
-- ((in_int_x+in_int_x)>9): 9;
(in_int_x > 4): 9;
(step=1) : secret;
(step=2) : in_int_x+in_int_x;
(step=7) : secret;
(step=8) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0 | step=7) : {0,1,2,3};
TRUE: secret;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
(step=6) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=3) : int_k+1;
(step=9) : int_k+1;
TRUE: int_k;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=4)& !(int_k=0)): in_int_x mod int_k;
((step=10)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=11);
MODULE main
VAR
step: 0..12;
in_int_x: 0..9;
in_int_y: 0..3;
int_k: 0..3;
secret: 0..9;
obs_public_out: 0..3;
ASSIGN
-- L0:
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: if (k == 0 || k == y)
-- L1: {x := in_secretput();}
-- L2: else {x := x + x;}
-- L3: k := k + 1;
-- L4: obs_public_output = (x % k);
-- L5: while (k < 3) {
-- L6: y = input()
-- L7: if (k == 0 || k == y) {
-- L8: x := in_secretput();}
-- L9: else {x := x;} --error
-- L10: k := k + 1;
-- L11: obs_public_output(x % k);
-- L12: END
init(step):= 0;
next(step):=
case
((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
(step=1): {3};
(step=2): {3};
(step=3): {4};
(step=4): {5};
((step=5) & (int_k<3)): {6};
((step=5) & !(int_k<3)): {11};
((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
(step=7): {9};
(step=8): {9};
(step=9): {10};
(step=10): {5};
(step=11): {11};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
(in_int_x>4): 9;
(step=1) : secret;
(step=2) : in_int_x;--error
(step=7) : secret;
(step=8) : in_int_x;--error
TRUE: in_int_x;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0 | step=7) : {0,1,2,3};
TRUE: secret;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
(step=6) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=3) : int_k+1;
(step=9) : int_k+1;
TRUE: int_k;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=4)& !(int_k=0)): in_int_x mod int_k;
((step=10)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=11);
MODULE main
VAR
step: 0..12;
in_int_x: 0..9;
in_int_y: 0..3;
secret: 0..9;
int_k: 0..3;
obs_public_out: 0..3;
loop_count: 0..2;
ASSIGN
-- for loop i in range(2)
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L1: while (k < 3) {
-- L2: if (k == 0 || k == y) {
-- L3: x := secretput();}
-- L4: else {x := x + x;}
-- L5: k := k + 1;
-- L6: obs_public_output(x % k);
-- L7: END
init(step):= 0;
next(step):=
case
(loop_count=2): step; -- terminate
(step=0): {1};
((step=1) & (int_k<3)): {2};
((step=1) & !(int_k<3)): {6};
((step=2) & ((int_k=0) | (int_k=in_int_y))): {3};
((step=2) & !((int_k=0) | (int_k=in_int_y))): {4};
(step=3): {5};
(step=4): {5};
(step=4): {5};
(step=5): {1};
(step=6): {7};
(step=7): {0};
TRUE: step;
esac;
init(loop_count) := 0;
next(loop_count) :=
case
(loop_count=2): loop_count;
(step=7): loop_count+1;
TRUE: loop_count;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
(step=0) : 0;
((in_int_x+in_int_x)>9): 9;
(step=3) : secret;
(step=4) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(step=0) : 0;
(int_k=3): 3;
(step=5) : int_k+1;
TRUE: int_k;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0) : {0,1,2,3};
TRUE: secret;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=6)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=0 & loop_count=2);
MODULE main
VAR
step: 0..12;
in_int_x: 0..9;
in_int_y: 0..3;
int_k: 0..3;
secret: 0..9;
obs_public_out: 0..3;
loop_count: 0..2;
ASSIGN
-- L0: for i in range(2)
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: if (k == 0 || k == y)
-- L1: {x := in_secretput();}
-- L2: else {x := x + x;}
-- L3: k := k + 1;
-- L4: obs_public_output = (x % k);
-- L5: while (k < 3) {
-- L6: y = input()
-- L7: if (k == 0 || k == y) {
-- L8: x := in_secretput();}
-- L9: else {x := x + x;}
-- L10: k := k + 1; }
-- L11: obs_public_output(x % k) ;
-- L12: END
init(step):= 0;
next(step):=
case
(loop_count=2): step; -- terminate
((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
(step=1): {3};
(step=2): {3};
(step=3): {4};
(step=4): {5};
((step=5) & (int_k<3)): {6};
((step=5) & !(int_k<3)): {11};
(step=6): {7};
((step=7) & ((int_k=0) | (int_k=in_int_y))): {8};
((step=7) & !((int_k=0) | (int_k=in_int_y))): {9};
(step=8): {10};
(step=9): {10};
(step=10): {5};
(step=11): {12};
(step=12): {0};
TRUE: step;
esac;
init(loop_count) := 0;
next(loop_count) :=
case
(loop_count=2): loop_count;
(step=12): loop_count+1;
TRUE: loop_count;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
(step=0) : 0;
((in_int_x+in_int_x)>9): 9;
(step=1) : secret;
(step=2) : in_int_x+in_int_x;
(step=7) : secret;
(step=8) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0 | step=7) : {0,1,2,3};
TRUE: secret;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
(step=6) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(step=0) : 0;
(int_k=3): 3;
(step=3) : int_k+1;
(step=9) : int_k+1;
TRUE: int_k;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=4)& !(int_k=0)): in_int_x mod int_k;
((step=11)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=0 & loop_count=2);
MODULE main
VAR
step: 0..12;
in_int_x: 0..9;
in_int_y: 0..3;
int_k: 0..3;
secret: 0..9;
obs_public_out: 0..3;
ASSIGN
-- L0:
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: if (k == 0 || k == y)
-- L1: {x := in_secretput();}
-- L2: else {x := x + x;}
-- L3: k := k + 1;
-- L4: obs_public_output = (x % k);
-- L5: while (k < 3) {
-- L6: y = input()
-- L7: if (k == 0 || k == y) {
-- L8: x := in_secretput();}
-- L9: else {x := x;} --error
-- L10: k := k + 1;
-- L11: obs_public_output(x % k);
-- L12: END
init(step):= 0;
next(step):=
case
((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
(step=1): {3};
(step=2): {3};
(step=3): {4};
(step=4): {5};
((step=5) & (int_k<3)): {6};
((step=5) & !(int_k<3)): {11};
((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
(step=7): {9};
(step=8): {9};
(step=9): {10};
(step=10): {5};
(step=11): {11};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
((in_int_x+in_int_x)>9): 9;
(step=1) : secret;
(step=2) : in_int_x;--error
(step=7) : secret;
(step=8) : in_int_x;--error
TRUE: in_int_x;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0 | step=7) : {0,1,2,3};
TRUE: secret;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
(step=6) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=3) : int_k+1;
(step=9) : int_k+1;
TRUE: int_k;
esac;
init(obs_public_out) := 0;
next(obs_public_out) :=
case
((step=4)& !(int_k=0)): in_int_x mod int_k;
((step=10)& !(int_k=0)): in_int_x mod int_k;
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=11);
MODULE main
VAR
step: 0..9;
int_x: 0..15;
int_k: 0..3;
in_secret: 0..3;
out_public: 0..3;
ASSIGN
-- D = 32
-- L0:
-- L1: x = 0
-- L2: k = 0
-- L3: while (k < 3) {
-- L4: if (k == 0) {
-- L5: x := in_secretput();}
-- L6: else {x := x + x;}
-- L7: k := k + 1;
-- L8: out_public((4 + (x - 4)) % ((k - k) + 3));
-- L9: END
init(step):= 0;
next(step):=
case
(step=0): {1};
(step=1): {2};
(step=2): {3};
((step=3) & (int_k<3)): {4};
((step=3) & !(int_k<3)): {9};
((step=4) & (int_k=0)): {5};
((step=4) & !(int_k=0)): {6};
(step=5): {7};
(step=6): {7};
(step=7): {8};
(step=8): {3};
(step=9): {9};
TRUE: step;
esac;
init(int_x) := 0;
next(int_x) :=
case
(int_x > 7): 15;
(step=5) : in_secret;
(step=6) : int_x + int_x;
TRUE: int_x;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=7) : int_k + 1;
TRUE: int_k;
esac;
init(out_public) := 0;
next(out_public) :=
case
-- ((step=8)& !(int_k=0)): (4 + (int_x - 4)) mod ((int_k - int_k) + 3);
((step=8)& !(int_k=0)): int_x mod 3;
TRUE: out_public;
esac;
init(in_secret) := {0, 1, 2, 3};
next(in_secret) := in_secret;
DEFINE
halt := (step=9);
MODULE main
VAR
step: 0..22;
int_x: 0..9;
int_k: 0..3;
in_secret: 0..3;
out_public: 0..3;
move: boolean;
temp0: 0..7;
temp1: 0..11;
temp2: 0..5;
temp3: 0..5;
ASSIGN
-- (diameter: 25)
-- L0:
-- L1: x = 0
-- L2: k = 0
-- L3: if (k == 0)
-- L4: {x := in_secretput();}
-- L5: else {x := x + x;}
-- L6: k := k + 1;
-- L7: temp0 = (x-4);
-- L8: temp1 = (4+temp0)
-- L9: temp2 = (k-k);
-- L10: temp3 = (temp2-3);
-- L11: public_output = (x % k);
-- L12: while (k < 3) {
-- L13: if (k == 0) {
-- L14: x := in_secretput();}
-- L15: else {x := x + x;}
-- L16: k := k + 1;
-- L17: temp0 = (x-4);
-- L18: temp1 = (4+temp0);
-- L19: temp2 = (k-k);
-- L20: temp3 = (temp2-3);
-- L21: out_public=temp1 % temp3; }
-- L22: END
init(step):= 0;
next(step):=
case
(step=0): {1};
(step=1): {2};
(step=2): {3};
((step=3) & (int_k=0)): {4};
((step=3) & (!(int_k=0))): {5};
(step=4): {6};
(step=5): {6};
(step=6): {7};
(step=7): {8};
(step=8): {9};
(step=9): {10};
(step=10): {11};
(step=11): {12};
((step=12) & (int_k<3)): {13};
((step=12) & (!(int_k<3))): {22};
((step=13) & (int_k=0)): {14};
((step=13) & (!(int_k=0))): {15};
(step=14): {16};
(step=15): {16};
(step=16): {17};
(step=17): {18};
(step=18): {19};
(step=19): {20};
(step=20): {21};
(step=21): {12};
(step=22): {22};
TRUE: step;
esac;
init(temp0) := 0;
next(temp0) :=
case
((step=7) & (int_x>4)): (int_x - 4);
((step=7) & (int_x<=4)): 0;
((step=17) & (int_x>4)): (int_x - 4);
((step=17) & (int_x<=4)): 0;
TRUE: temp0;
esac;
init(temp1) := 0;
next(temp1) :=
case
(step=8): (4+temp0);
(step=18): (4+temp0);
TRUE: temp1;
esac;
init(temp2) := 0;
next(temp2) :=
case
(step=9): (int_k - int_k);
(step=19): (int_k - int_k);
TRUE: temp2;
esac;
init(temp3) := 0;
next(temp3) :=
case
((step=10) & (temp2>3)): (temp2 - 3);
((step=10) & (temp2<=3)): 0;
((step=20) & (temp2>3)): (temp2 - 3);
((step=20) & (temp2<=3)): 0;
TRUE: temp3;
esac;
init(int_x) := 0;
next(int_x) :=
case
-- ((int_x+int_x)>9): 9;
(int_x > 4): 9;
(step=4) : in_secret;
(step=5) : int_x+int_x;
(step=14) : in_secret;
(step=15) : int_x+int_x;
TRUE: int_x;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=6) : int_k+1;
(step=16) : int_k+1;
TRUE: int_k;
esac;
init(out_public) := 0;
next(out_public) :=
case
-- ((step=11)& !(int_k=0)): temp1 mod temp3;
-- ((step=21)& !(int_k=0)): temp1 mod temp3;
((step=11)& !(int_k=0)): int_x mod 3;
((step=21)& !(int_k=0)): int_x mod 3;
TRUE: out_public;
esac;
init(in_secret) := {0, 1, 2, 3};
next(in_secret) := in_secret;
DEFINE
halt := (step=22);
MODULE main
VAR
step: 0..15;
in_int_x: 0..9;
in_int_y: 0..3;
secret: 0..9;
int_k: 0..3;
obs_public_out: 0..3;
ASSIGN
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: while (k < 3) {
-- L1: if (k == 0 || k == y) {
-- L2: x := secretput();}
-- L3: else {x := x + x;}
-- L4: k := k + 1;
-- L5: obs_public_output(x % k);
-- L6: END
init(step):= 0;
next(step):=
case
((step=0) & (int_k<3)): {1};
((step=0) & !(int_k<3)): {6};
((step=1) & ((int_k=0) | (int_k=in_int_y))): {2};
((step=1) & !((int_k=0) | (int_k=in_int_y))): {3};
(step=2): {4};
(step=3): {4};
(step=4): {5};
(step=5): {0};
(step=6): {6};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
((in_int_x+in_int_x)>9): 9;
(step=2) : secret;
(step=3) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=5) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=4) : int_k+1;
TRUE: int_k;
esac;
init(secret) := 0;
next(secret) :=
case
(step=1) : {0,1,2,3};
TRUE: secret;
esac;
-- obs_public = (4 + (x - 4)) % (( k - k ) + 3) }
init(obs_public_out) := 0;
next(obs_public_out) :=
case
-- ((step=5) & (in_int_x <= 4)): obs_public_out;
((step=5)): (in_int_x) mod ((int_k - int_k) + 3);
TRUE: obs_public_out;
esac;
DEFINE
halt := (step=6);
MODULE main
VAR
step: 0..15;
in_int_x: 0..9;
in_int_y: 0..3;
int_k: 0..3;
secret: 0..9;
obs_public_out: 0..3;
temp0: 0..5;
temp2: 0..1;
temp3: 0..3;
ASSIGN
-- L0:
-- L0: x = 0
-- L0: k = 0
-- L0: y = input()
-- L0: if (k == 0 || k == y)
-- L1: {x := in_secretput();}
-- L2: else {x := x + x;}
-- L3: k := k + 1;
-- L4: obs_public_output = (x % k);
-- L5: while (k < 3) {
-- L6: y = input()
-- L7: if (k == 0 || k == y) {
-- L8: x := in_secretput();}
-- L9: else {x := x + x;}
-- L10: k := k + 1;
-- L11: temp0 = x-4, temp1 = temp0+4
-- L12: temp2 = k - k
-- L13: temp3 = temp2 + 3
-- L14: obs_public = (4 + temp0) % temp3 }
-- L15: END
init(step):= 0;
next(step):=
case
((step=0) & ((int_k=0) | (int_k=in_int_y))): {1};
((step=0) & !((int_k=0) | (int_k=in_int_y))): {2};
(step=1): {3};
(step=2): {3};
(step=3): {4};
(step=4): {5};
((step=5) & (int_k<3)): {6};
((step=5) & !(int_k<3)): {11};
((step=6) & ((int_k=0) | (int_k=in_int_y))): {7};
((step=6) & !((int_k=0) | (int_k=in_int_y))): {8};
(step=7): {9};
(step=8): {9};
(step=9): {10};
(step=10): {5};
(step=11): {12};
(step=12): {13};
(step=13): {14};
(step=14): {15};
TRUE: step;
esac;
init(in_int_x) := 0;
next(in_int_x) :=
case
((in_int_x+in_int_x)>9): 9;
(step=1) : secret;
(step=2) : in_int_x+in_int_x;
(step=7) : secret;
(step=8) : in_int_x+in_int_x;
TRUE: in_int_x;
esac;
init(secret) := 0;
next(secret) :=
case
(step=0 | step=7) : {0,1,2,3};
TRUE: secret;
esac;
init(in_int_y) := 0;
next(in_int_y) :=
case
(step=0) : {1,2,3};
(step=6) : {1,2,3};
TRUE: in_int_y;
esac;
init(int_k) := 0;
next(int_k) :=
case
(int_k=3): 3;
(step=3) : int_k+1;
(step=9) : int_k+1;
TRUE: int_k;
esac;
-- obs_public = (4 + (x - 4)) % (( k - k ) + 3) }
init(obs_public_out) := 0;
next(obs_public_out) :=
case
-- ((step=4) & (in_int_x <= 4)): obs_public_out;
-- ((step=12) & (in_int_x <= 4)): obs_public_out;
((step=4) & !(temp3=0)): (in_int_x) mod (temp3);
((step=14) & !(temp3=0)): (in_int_x) mod (temp3);
TRUE: obs_public_out;
esac;
init(temp0) := 0;
next(temp0) :=
case
(step=11 & (in_int_x <= 4)): 0;
(step=11): (in_int_x - 4);
TRUE: temp0;
esac;
init(temp2) := 0;
next(temp2) :=
case
(step=12): (int_k - int_k);
-- (step=12): 0;
TRUE: temp2;
esac;
init(temp3) := 0;
next(temp3) :=
case
(step=13 & !(temp2=0)): 3;
(step=13): (temp2 + 3);
TRUE: 3;
esac;
DEFINE
halt := (step=15);
MODULE main
VAR
PC: 0..4;
in_secret: 0..3;
out_secret: 0..3;
out_public: 0..3;
ASSIGN
-- L0: x := in_secretput()
-- L1: if (0):
-- L2: out_publicput(x)
-- L3: else: out_secretput(x)
-- L4: END
init(PC):= 0;
next(PC):=
case
(PC=0): {1};
((PC=1) & (FALSE)): {2};
((PC=1) & (!(FALSE))): {3};
(PC=2): {4};
(PC=3): {4};
TRUE: PC;
esac;
init(out_public) := 0;
next(out_public) :=
case
(PC=2): in_secret;
TRUE: out_public;
esac;
init(out_secret) := 0;
next(out_secret) :=
case
(PC=3): in_secret;
TRUE: out_secret;
esac;
init(in_secret) := {0, 1};
next(in_secret) := in_secret;
DEFINE
halt := (PC=4);
MODULE main
VAR
PC: 0..2;
in_secret: 0..3;
out_secret: 0..3;
out_public: 0..3;
ASSIGN
-- L0: x := in_secretput()
-- L1: out_secretput(x)
-- L2: END
init(PC):= 0;
next(PC):=
case
(PC=0): {1};
(PC=1): {2};
TRUE: PC;
esac;
init(out_public) := 0;
next(out_public) := out_public;
init(out_secret) := 0;
next(out_secret) := in_secret;
init(in_secret) := {0, 1};
next(in_secret) := in_secret;
DEFINE
halt := (PC=2);
MODULE main
VAR
PC: 0..6;
loop_count: 0..3;
-- secret_in: 0..1;
-- ndet_in: 0..1;
in_var_x: 0..1;
in_var_y: 0..1;
obs_out: 0..2;
ASSIGN
-- for i in rnage(3) -- loop 3 times
-- L0: x := secret_input()
-- L0: y := ndet_input()
-- L1: if (x == y):
-- L2: if (0):
-- L3: out(x)
-- L4: else: out(x)
-- L5: else: out(!x)
-- L6: END
init(PC):= 0;
next(PC):=
case
(PC=0): {1};
((PC=1) & (in_var_x=in_var_y)): {2};
((PC=1) & (!(in_var_x=in_var_y))): {5};
((PC=2) & (FALSE)): {3};
((PC=2) & (!(FALSE))): {4};
(PC=3): {6};
(PC=4): {6};
(PC=5): {6};
((PC=6) & (loop_count<3)): {0}; -- loop back
((PC=6) & (loop_count=3)): {6}; -- terminate
TRUE: PC;
esac;
init(loop_count) := 0;
next(loop_count) :=
case
(loop_count=3): loop_count;
(PC=0): loop_count+1;
TRUE: loop_count;
esac;
init(obs_out) := 0;
next(obs_out) :=
case
((PC=6) & (loop_count=3)): obs_out;
(PC=3): in_var_x;
(PC=4): in_var_x;
((PC=5) & (in_var_x=0)): 1;
((PC=5) & (in_var_x=1)): 0;
TRUE: obs_out;
esac;
init(in_var_x) := {0, 1};
next(in_var_x) :=
case
((PC=6) & (loop_count=3)) : in_var_x; -- terminate
(PC=6) : {0, 1}; --re-fetch input
TRUE: in_var_x;
esac;
init(in_var_y) := {0, 1};
next(in_var_y) :=
case
((PC=6) & (loop_count=3)) : in_var_y; -- terminate
(PC=6) : {0, 1}; --re-fetch input
TRUE: in_var_y;
esac;
DEFINE
halt := ((PC=6) & (loop_count=3));
MODULE main
VAR
PC: 0..4;
loop_count: 0..3;
-- secret_in: 0..1;
-- ndet_in: 0..1;
in_var_x: 0..1;
in_var_y: 0..1;
obs_out: 0..3;
ASSIGN
-- for i in rnage(3) -- loop 3 times
-- L0: x := secret_input()
-- L0: y := ndet_input()
-- L1: if (x == y):
-- L2: out(x)
-- L3: else: out(!x)
-- L4: END
init(PC):= 0;
next(PC):=
case
(PC=0): {1};
((PC=1) & (in_var_x=in_var_y)): {2};
((PC=1) & (!(in_var_x=in_var_y))): {3};
(PC=2): {4};
(PC=3): {4};
((PC=4) & (loop_count<3)): {0}; -- loop back
((PC=4) & (loop_count=3)): {4}; -- terminate
TRUE: PC;
esac;
init(loop_count) := 0;
next(loop_count) :=
case
(loop_count=3): loop_count;
(PC=0): loop_count+1;
TRUE: loop_count;
esac;
init(obs_out) := 0;
next(obs_out) :=
case
((PC=4) & (loop_count=3)) : obs_out; --terminate
(PC=2): in_var_x;
((PC=3)&(in_var_x=1)): 0;
((PC=3)&(in_var_x=0)): 1;
TRUE: obs_out;
esac;
init(in_var_x) := {0, 1};
next(in_var_x) :=
case
((PC=4) & (loop_count=3)) : in_var_x; --terminate
(PC=4) : {0, 1}; --re-fetch input
TRUE: in_var_x;
esac;
init(in_var_y) := {0, 1};
next(in_var_y) :=
case
((PC=4) & (loop_count=3)) : in_var_y; --terminate
(PC=4) : {0, 1}; --re-fetch input
TRUE: in_var_y;
esac;
DEFINE
halt := ((PC=4) & (loop_count=3));
The HyperLTL formula¶
All three optimisations reuse the same observational determinism property: any two traces of the source must match the public outputs of a witness trace, reflecting that the optimised program does not expose new public information.
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G(((obs_public_out[A][t] = 0) & (obs_public_out[B][t] = 0)) | ((obs_public_out[A][t] = 1) & (obs_public_out[B][t] = 1)) | ((obs_public_out[A][t] = 2) & (obs_public_out[B][t] = 2)) | ((obs_public_out[A][t] = 3) & (obs_public_out[B][t] = 3)))
Forall A . Forall B . E t . G(((out_public[A][t] = 0) & (out_public[B][t] = 0)) | ((out_public[A][t] = 1) & (out_public[B][t] = 1)) | ((out_public[A][t] = 2) & (out_public[B][t] = 2)) | ((out_public[A][t] = 3) & (out_public[B][t] = 3)))
Forall A . Forall B . E t . G
((obs_out[A][t] = 0) & (obs_out[B][t] = 0)
|
(obs_out[A][t] = 1) & (obs_out[B][t] = 1)
|
(obs_out[A][t] = 2) & (obs_out[B][t] = 2))
Forall A . Forall B . E t . G
((obs_out[A][t] = 0) & (obs_out[B][t] = 0)
|
(obs_out[A][t] = 1) & (obs_out[B][t] = 1)
|
(obs_out[A][t] = 2) & (obs_out[B][t] = 2))