A Design and Verification Methodology for Secure Isolated...

159
A Design and Verification Methodology for Secure Isolated Regions Rohit Sinha 1 , Manuel Costa 2 , Akash Lal 2 , Nuno P. Lopes 2 , Sriram Rajamani 2 , Sanjit A. Seshia 1 , Kapil Vaswani 2 2 1 PLDI 2016

Transcript of A Design and Verification Methodology for Secure Isolated...

A Design and Verification Methodology for Secure Isolated Regions

Rohit Sinha1, Manuel Costa2, Akash Lal2, Nuno P. Lopes2,Sriram Rajamani2, Sanjit A. Seshia1, Kapil Vaswani2

21

PLDI 2016

Secure Isolated Regions (SIR)

2

Secure Isolated Regions (SIR)

2

App

Operating System

Hypervisor

Secure Isolated Regions (SIR)

2

App

Operating System

Hypervisor

Secure Hardware

IntelSGX

ARMTrustZone

Secure Isolated Regions (SIR)

SIR memory is protected: only SIR code can access it

2

App

Operating System

Hypervisor

Secure Hardware

IntelSGX

ARMTrustZone

SIR

Secure Isolated Regions (SIR)

SIR memory is protected: only SIR code can access it

Trusted Computing Base includes the SIR and CPU hardware

2

App

Operating System

Hypervisor

Secure Hardware

IntelSGX

ARMTrustZone

SIR

Secure Isolated Regions (SIR)

SIR memory is protected: only SIR code can access it

Trusted Computing Base includes the SIR and CPU hardware

2

AppHadoopSIR

Operating System

Hypervisor

Secure Hardware

IntelSGX

ARMTrustZone

VC3: Trustworthy Data Analytics in the Cloud [Schuster et. al., S&P’15]

void map(...) { /* compute on sensitive data */ }

void reduce(...) { /* compute on sensitive data */ }

SIR

Bugs in SIRs can be Exploited

3

HadoopSIR

Secure Hardware

IntelSGX

Bugs in SIRs can be Exploited

SIR accesses untrusted Hadoop’s memory to perform I/O

3

HadoopSIR

Secure Hardware

IntelSGX

Bugs in SIRs can be Exploited

SIR accesses untrusted Hadoop’s memory to perform I/O

3

HadoopSIR

Secure Hardware

IntelSGX

MapperSIRHadoop

MapperSIRHadoop

Reducer SIR

encrypted (k,v)

//decrypt; compute

Bugs in SIRs can be Exploited

SIR accesses untrusted Hadoop’s memory to perform I/O

Adversary can exploit SIRs using I/O interactions

3

HadoopSIR

Secure Hardware

IntelSGX

MapperSIRHadoop

MapperSIRHadoop

e.g. Heartbleed, unsafe gcc

optimizations

Reducer SIR

encrypted (k,v)

//decrypt; compute

Bugs in SIRs can be Exploited

SIR accesses untrusted Hadoop’s memory to perform I/O

Adversary can exploit SIRs using I/O interactions

Our goal: ensure that secrets are not leaked (confidentiality) in the presence of programming errors and compiler bugs

3

HadoopSIR

Secure Hardware

IntelSGX

MapperSIRHadoop

MapperSIRHadoop

e.g. Heartbleed, unsafe gcc

optimizations

Reducer SIR

encrypted (k,v)

//decrypt; compute

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) {

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v);

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum);

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

void Reduce(byte *kEnc, byte *vEnc) { KeyAesGcm *aesKey = ProvisionKey();

char k[..]; aesKey->Decrypt(kEnc, k); char v[..]; aesKey->Decrypt(vEnc, v); long sum = compute_sum(v);

char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); aesKey->Encrypt(cleartext, untrusted_memory, BUF_SIZE);}

Challenges in Proving Confidentiality

4

HadoopSIR

Secure Hardware

IntelSGX

compiler

Information Release Confinement

5

HadoopSIR

Information Release Confinement

5

HadoopSIRUser Code(U)

Runtime Library

(L)

L implements send, recv, malloc, free

Information Release Confinement

5

HadoopSIRUser Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

void Reduce(byte *kEnc, byte *vEnc) { char *k = recv(..); char *v = recv(..);

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

void Reduce(byte *kEnc, byte *vEnc) { char *k = recv(..); char *v = recv(..); long sum = compute_sum(v);

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

void Reduce(byte *kEnc, byte *vEnc) { char *k = recv(..); char *v = recv(..); long sum = compute_sum(v); char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); send(cleartext, ..);}

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

5

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

void Reduce(byte *kEnc, byte *vEnc) { char *k = recv(..); char *v = recv(..); long sum = compute_sum(v); char cleartext[..]; sprintf(cleartext, “%s %lld”, k, sum); send(cleartext, ..);}

IRC: All updates to non-SIR memory via L’s send API

Separation of concerns:U does not

manage crypto keys or write to

untrusted memory

Information Release Confinement

6

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

Information Release Confinement

6

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

send(secret)

L implements send, recv, malloc, free

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

6

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

✓ Prevents explicit information leaks: side channels outside scope

send(secret)

L implements send, recv, malloc, free

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

6

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

✓ Prevents explicit information leaks: side channels outside scope

✓ Even if U is buggy, an adversary only sees encrypted values in an exploit

send(secret)

L implements send, recv, malloc, free

IRC: All updates to non-SIR memory via L’s send API

Information Release Confinement

6

HadoopSIR...f12e6dafa9d3b

...c96a8ebbd4a7e

ciphertext messages

User Code(U)

Runtime Library

(L)

✓ Prevents explicit information leaks: side channels outside scope

✓ Even if U is buggy, an adversary only sees encrypted values in an exploit

send(secret)

L implements send, recv, malloc, free

✓ Avoids fine-grained tracking of secrets in U’s memory: all of U is secret

IRC: All updates to non-SIR memory via L’s send API

Proving Information Release Confinementsatisfies IRCSIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L

SIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

SIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

implement a cryptographically secure channel

send, recv

SIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

implement a cryptographically secure channel

send, recv U calls into L at API entrypoints

SIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

implement a cryptographically secure channel

send, recv U does not write to non-SIR

memory

U calls into L at API entrypoints

SIR

7

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

implement a cryptographically secure channel

send, recv U does not write to non-SIR

memory

U calls into L at API entrypoints

SIR

7

✓ We don’t require full functional correctness of U

Proving Information Release Confinementsatisfies IRC

Correctness of L Correctness of U

implement a cryptographically secure channel

send, recv U does not write to non-SIR

memory

U calls into L at API entrypoints

✓ Proof strategy requires no annotations from the developer

SIR

7

✓ We don’t require full functional correctness of U

Contributions

8

Contributions

8

Formal Specification of IRC

IRC as a design methodology for programming SIRs

Contributions

8

Sound Decomposition of IRC proof into Contracts on U and L

Formal Specification of IRC

IRC as a design methodology for programming SIRs

Contributions

8

Sound Decomposition of IRC proof into Contracts on U and L

Automatic, Modular Verifier for proving IRC on U’s binary

Verifier checks against a privileged OS-level adversary

Formal Specification of IRC

IRC as a design methodology for programming SIRs

Contributions

8

Sound Decomposition of IRC proof into Contracts on U and L

Automatic, Modular Verifier for proving IRC on U’s binary

Verifier checks against a privileged OS-level adversary

Evaluation on several SIRs

Map-Reduce benchmarks from VC3

SPEC benchmarks

Formal Specification of IRC

IRC as a design methodology for programming SIRs

This Talk: Automatically Proving IRC

9

This Talk: Automatically Proving IRC

Verifying that U calls into L at API entrypointsVerifying Calls in U

9

This Talk: Automatically Proving IRC

Verifying that U calls into L at API entrypoints

Verifying that U does not modify non-SIR memory

Verifying Calls in U

Verifying Writes in U

9

This Talk: Automatically Proving IRC

Verifying that U calls into L at API entrypoints

Verifying that U does not modify non-SIR memory

Correctness properties of L

Verifying Calls in U

Verifying Writes in U

Verifying L

9

This Talk: Automatically Proving IRC

Verifying that U calls into L at API entrypoints

Verifying that U does not modify non-SIR memory

Correctness properties of L

Evaluation on VC3 and SPEC

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

9

Verifying U: Calls to L via API Entrypoints

10

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

buf

Verifying U: Calls to L via API Entrypoints

10

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

bufq

Verifying U: Calls to L via API Entrypoints

10

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

buf

q

Verifying U: Calls to L via API Entrypoints

10

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

buf

q

Verifying U: Calls to L via API Entrypoints

10

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

✓ A call instruction targets the starting address of a procedure in U or API of L

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

✓ A call instruction targets the starting address of a procedure in U or API of L

✓ A ret instruction returns back to the caller

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

✓ A call instruction targets the starting address of a procedure in U or API of L

✓ A ret instruction returns back to the caller

✓ A jmp instruction targets a legal instruction within the procedure

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

✓ A call instruction targets the starting address of a procedure in U or API of L

✓ A ret instruction returns back to the caller

✓ A jmp instruction targets a legal instruction within the procedure

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

EvaluationWeak (WCFI)

SIR memory

*q = buf + input; *q = input2;... return;

return addr

arbitrary code

buf

q

Verifying U: Calls to L via API Entrypoints

10

✓ A call instruction targets the starting address of a procedure in U or API of L

✓ A ret instruction returns back to the caller

✓ A jmp instruction targets a legal instruction within the procedure

Control Flow Integrity

arbitrary code- middle of x86 instructions- arbitrary instructions in L

Potential Code in U

Verifying Calls in U

Verifying Writes in U

Verifying L

EvaluationWCFI ⇒

U calls into L via APIs

Weak (WCFI)

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

not-writablereturn addresses

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

not-writablereturn addresses

writablelocal varsheap objects

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

bufq

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

not-writablereturn addresses

writablelocal varsheap objects

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

q

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

not-writablereturn addresses

writablelocal varsheap objects

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

q

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

bitmap

not-writablereturn addresses

writablelocal varsheap objects

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

SIR memory

*q = buf + input;*q = input2;...return;

return addr

buf

q

Runtime check using VC3 compiler:is address of q marked writable in bitmap?

Software TRAP

bitmap

not-writablereturn addresses

writablelocal varsheap objects

Verifying U: Runtime Checks for WCFI

11

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Potential Code in U

Verifying U: Modeling U’s Binary

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modeling U’s Binary

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugs

Verifying U: Modeling U’s Binary

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugsCompiler optimizes away many runtime checks

Verifying U: Modeling U’s Binary

...mov rcx, [rax+rbx]bt rcx, rbxjb $L2int 3$L2: mov [rbx],rdx ... ret

x64 code produced by compiler

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugsCompiler optimizes away many runtime checks

Verifying U: Modeling U’s Binary

Binary Analysis Platform

...mov rcx, [rax+rbx]bt rcx, rbxjb $L2int 3$L2: mov [rbx],rdx ... ret

x64 code produced by compiler

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugsCompiler optimizes away many runtime checks

Verifying U: Modeling U’s Binary

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; mem := store(mem, rbx, rdx); ... return;

Binary Analysis Platform

...mov rcx, [rax+rbx]bt rcx, rbxjb $L2int 3$L2: mov [rbx],rdx ... ret

x64 code produced by compiler

Boogie model

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugsCompiler optimizes away many runtime checks

Verifying U: Modeling U’s Binary

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; mem := store(mem, rbx, rdx); ... return;

Binary Analysis Platform

...mov rcx, [rax+rbx]bt rcx, rbxjb $L2int 3$L2: mov [rbx],rdx ... ret

x64 code produced by compiler

Boogie model

12

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Avoid trusting the compiler: Long history of bugsCompiler optimizes away many runtime checks

Verifying U: Modeling the Adversary

13

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modeling the Adversary

SIR memory

a

13

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

load from untrusted memory returns arbitrary value *load(mem,a) = ITE(SIR(a), mem[a], *);

Verifying U: Modeling the Adversary

SIR memory

a

13

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation[Moat CCS’15]: models all operations by a malicious OS e.g. generate interrupts, modify page tables, launch other SIRs, etc.

load from untrusted memory returns arbitrary value *load(mem,a) = ITE(SIR(a), mem[a], *);

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Proof Obligations guarantee WCFI ⇒

U calls into L via APIs

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

VC-gen+

SMT Solving

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Proof Obligations guarantee WCFI ⇒

U calls into L via APIs

Verifying U: Proof Obligations

...rcx := load(mem, rax +64 rbx);CF := (rcx >>64 rbx)[1:0];goto $L1, $L2;$L1: assume CF == 0; assume false;$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

VC-gen+

SMT Solving

14

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Presence of runtime checks helps SMT solver

to prove assert Ψ

Proof Obligations guarantee WCFI ⇒

U calls into L via APIs

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ... sprintf(cleartext, “%s %lld”,...); ...}

void sprintf(char *cleartext,...) { /* write to cleartext */}

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ... sprintf(cleartext, “%s %lld”,...); ...}

void sprintf(char *cleartext,...) { /* write to cleartext */}

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ... sprintf(cleartext, “%s %lld”,...); ...}

void sprintf(char *cleartext,...) { /* write to cleartext */}

verifier asserts writable(bitmap, addr) for each store

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ... sprintf(cleartext, “%s %lld”,...); ...}

void sprintf(char *cleartext,...) { /* write to cleartext */}

verifier asserts writable(bitmap, addr) for each store

addr

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

15

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ... sprintf(cleartext, “%s %lld”,...); ...}

void sprintf(char *cleartext,...) { /* write to cleartext */}

verifier asserts writable(bitmap, addr) for each store

addr

addr

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

16

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

16

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ...

sprintf(cleartext, “%s %lld”, ...); ...}

void sprintf(char *cleartext, ...) { /* write to cleartext */}

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

16

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ...

sprintf(cleartext, “%s %lld”, ...); ...}

void sprintf(char *cleartext, ...) { /* write to cleartext */}

store<compiler makes cleartext writable>

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

16

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ...

sprintf(cleartext, “%s %lld”, ...); ...}

void sprintf(char *cleartext, ...) { /* write to cleartext */}

verifier asserts that bitmap is updated safely

store<compiler makes cleartext writable>

Verifying U: Proof Obligations on store

SIR memory

stack

bitmap

return address

sprintf localvariables

cleartext

16

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

void Reduce(...) { ...

sprintf(cleartext, “%s %lld”, ...); ...}

void sprintf(char *cleartext, ...) { /* write to cleartext */}

verifier asserts that bitmap is updated safely

store<compiler makes cleartext writable>

Verifying U: Soundness

17

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Soundness

17

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

call:

ret:

jmp:

Verifying U: Soundness

17

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

call:

ret:

jmp:

Proof obligations imply WCFI ⇒

U calls into L via APIs

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input;*q = secret;...

buf

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input;*q = secret;...

bufq

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input;*q = secret;...

buf

q

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input;*q = secret;...

buf

q

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

SIR memory

*q = buf + input;*q = secret;...

buf

q

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Runtime check using VC3 compiler:is q within SIR range?

SIR memory

*q = buf + input;*q = secret;...

buf

q

Software TRAP

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Runtime check using VC3 compiler:is q within SIR range?

SIR memory

*q = buf + input;*q = secret;...

buf

q

Software TRAP

Verifying U: Preventing Writes Outside SIR

18

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Since we don’t trust the compiler:verifier asserts addrInSIR(addr) for each store

Runtime check using VC3 compiler:is q within SIR range?

Verifying U: Soundness

...$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

19

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Soundness

...$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

19

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation Proof Obligations for WCFI

Verifying U: Soundness

...$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

19

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation Proof Obligations for WCFI

Proof Obligations for writes within SIR

Verifying U: Soundness

...$L2: assume CF == 1; assert Ψ; mem := store(mem, rbx, rdx); ...assert φ;return;

19

Boogie modelVerifying Calls in U

Verifying Writes in U

Verifying L

Evaluation Proof Obligations for WCFI + = IRCProof Obligations

for writes within SIR

Verifying U: Modular Verification

20

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modular Verification

We perform modular reasoning of U’s binary without false positives.

20

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modular Verification

We perform modular reasoning of U’s binary without false positives.

The VC3 compiler generates enough runtime checks to allow this.

20

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modular Verification

We perform modular reasoning of U’s binary without false positives.

The VC3 compiler generates enough runtime checks to allow this.

void Reduce(...) { ... sprintf(cleartext, “%s %lld”, …); ...}void sprintf(char *cleartext, …) { //write to cleartext, which is stack-allocated}

20

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verifying U: Modular Verification

We perform modular reasoning of U’s binary without false positives.

The VC3 compiler generates enough runtime checks to allow this.

void Reduce(...) { ... sprintf(cleartext, “%s %lld”, …); ...}void sprintf(char *cleartext, …) { //write to cleartext, which is stack-allocated}

20

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

<runtime check that buf is in SIR memory>

Verification Optimizations

21

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verification Optimizations

21

assertret:Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verification Optimizations

21

assertret:

sound strategy for quantifier instantiation

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verification Optimizations

21

assertret:

split into disjoint arrays for bitmap and stack

sound strategy for quantifier instantiation

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Verification Optimizations

21

Removed hundreds of Z3 timeouts in our experiments

assertret:

split into disjoint arrays for bitmap and stack

sound strategy for quantifier instantiation

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

void *malloc(size_t size)void free(void *buf)

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

void *malloc(size_t size)void free(void *buf)// ensures ...

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

void *malloc(size_t size)void free(void *buf)// ensures ...

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Manual, One-time Verification of L

void send(void *buf, size_t size)void recv(void *buf, size_t size)// ensures no unsafe modification to U// ensures channel key is not modified// ensures ...

void *malloc(size_t size)void free(void *buf)// ensures ...

No requires clauseon U

22

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Evaluation

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

EvaluationRuntime checks incur 15% performance hit [Schuster et al.: VC3]

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Evaluation

timeout: 30 mins

Runtime checks incur 15% performance hit [Schuster et al.: VC3]

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Evaluation

timeout: 30 mins

Runtime checks incur 15% performance hit [Schuster et al.: VC3]

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

Evaluation

timeout: 30 mins

Runtime checks incur 15% performance hit [Schuster et al.: VC3]

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

verified in 4 hours

Evaluation

timeout: 30 mins

Runtime checks incur 15% performance hit [Schuster et al.: VC3]

Verifying Calls in U

Verifying Writes in U

Verifying L

Evaluation

verified in 4 hours

Related Work

Related WorkWork Application Technique Comparison

Related WorkWork Application Technique Comparison

Sinha et al: Moat CCS’15

Verifying Confidentiality of SGX Programs

Refinement type system for

non-interference

Requires global, precise tracking of secrets in machine

code

Related WorkWork Application Technique Comparison

Sinha et al: Moat CCS’15

Verifying Confidentiality of SGX Programs

Refinement type system for

non-interference

Requires global, precise tracking of secrets in machine

code

Myers et al:JIF

SOSP’97

Information Flow for Java

applicationsType system for non-interference

Requires annotations, and trust in language

runtime

Related WorkWork Application Technique Comparison

Sinha et al: Moat CCS’15

Verifying Confidentiality of SGX Programs

Refinement type system for

non-interference

Requires global, precise tracking of secrets in machine

code

Myers et al:JIF

SOSP’97

Information Flow for Java

applicationsType system for non-interference

Requires annotations, and trust in language

runtime

Hawblitzel et al:IronClad Apps

OSDI’14Functional

correctnessDeductive verification

Requires manual effort in writing invariants

Related WorkWork Application Technique Comparison

Sinha et al: Moat CCS’15

Verifying Confidentiality of SGX Programs

Refinement type system for

non-interference

Requires global, precise tracking of secrets in machine

code

Myers et al:JIF

SOSP’97

Information Flow for Java

applicationsType system for non-interference

Requires annotations, and trust in language

runtime

Hawblitzel et al:IronClad Apps

OSDI’14Functional

correctnessDeductive verification

Requires manual effort in writing invariants

Morisett et al: Rocksalt PLDI’12

Software Fault Isolation

Verified Machine Code Checker

extracted from Coq

different goal

64-bit version requires 100GB address

space

Takeaway Points

25

Takeaway Points

IRC as a design principle for SIRs:

25

Takeaway Points

IRC as a design principle for SIRs: • easier to verify than full functional correctness

25

Takeaway Points

IRC as a design principle for SIRs: • easier to verify than full functional correctness• avoids tracking of secrets in SIR’s memory

25

Takeaway Points

IRC as a design principle for SIRs: • easier to verify than full functional correctness• avoids tracking of secrets in SIR’s memory

Automatic, modular verification of IRC on SIR binaries, with a small trusted computing base

25

Takeaway Points

IRC as a design principle for SIRs: • easier to verify than full functional correctness• avoids tracking of secrets in SIR’s memory

Automatic, modular verification of IRC on SIR binaries, with a small trusted computing base

https://github.com/TrustedCloud/slashconfidential

25