* Overview ** Attestation is powerful: lots of things easier if you know what code a remote party is running *** Especially relevant in a cloud context where you're outsourcing your computation to someone you might not trust ** Existing solutions aren't particularly flexible: *** attest to VM state, eg Terra, vTPM: requires knowing that a VM hash is OK *** can possibly attest to application in guest (Sailer '04) -- requires trusting a hash chain of all applications plus trusting kernel **** These change more frequently than you might like! (kernel updates etc) **** And maybe you want your cloud provider to be able to update these things. *** alternatively, highly-secure trusted execution platform (Flicker) **** pretty restrictive -- basically no services provided (FS storage, communication), interaction with untrusted code **** certainly can't reuse legacy code without serious modifications ** Our goal: provide an attestation for an application's identity and integrity *independent of* the operating system it's running on ** Not trying to provide absolute minimal TCB but rather something that can be used for the vast majority of cases where users aren't willing to completely refactor their application but would still like some more assurance. *** support existing applications offers a stepping stone to more secure ones *** allow trusted applications to coexist and interact with untrusted ones (subject to the obvious caveat) ** Achieve this goal with the combination of a VM-based isolation architecture (Overshadow) and a verification layer that interposes on system calls to validate results * Use cases ** Managed hosting (is this PaaS?) *** User is running an app, say a database server *** Cloud provider is responsible for updating the kernel and the other random daemons (sshd, nfs, etc) and config files **** probably don't want these in your attestation measurement because they're changing without your knowledge **** might not trust the cloud provider (example) ** In-guest agents *** Cloud provider is providing a backup service *** For better security, the backup server wants to only talk to the approved backup software the provider is running in the client's VM **** But the client has root access, can tamper with the OS ** VPS hosting (jails, vservers) *** Similar to managed hosting -- here the OS is clearly being managed by the provider *** Nice example in that there's no existing VM, so could use a thin hypervisor like TrustVisor for a reasonably small TCB. * Model and Assumptions ** Picture *** VMM runs one or more VMs. Each VM consists of a guest OS and some applications. Some may be trusted, others untrusted. *** "application" = one or more processes allowed to run with access to specific data *** Hardware (TPM), VMM, application trusted. OS and untrusted apps aren't. ** Guarantees *** Strong integrity: you are running the right code and it is doing what it should be *** Weaker confidentiality: we can make sure the untrusted OS doesn't directly access your data in memory or files, but side channel attacks could still be a problem *** No guarantee of availability: if there's an attempted integrity violation the system just stops **** If you care, use replication * Isolation ** First step is to have some sort of isolation architecture *** Provides protection for application memory (code+data), processor state, and control flow => integrity for applications that don't make syscalls * Identity and Attestation ** How is an application identified? (We were vague before...) *** By an application definition file **** the hash of an initial state (e.g. a rpm or tar) **** a list of executables that can be invoked with that application's privilege (SID) **** and some configuration, e.g. which protected/unprotected files it's allowed to access *** What does this guarantee? **** the program's current state is one derived from running the specified code from the specified initial state **** so if you trust the initial installation, and you trust us to ensure execution integrity, you know you're interacting with the right code ** The chain of trust *** Trusted VMM is securely booted using hardware (TPM) mechanisms which can attest to a hash of its binary image -- standard trusted bootstrap story *** VMM enters protected execution only on request from the shim, and only after verifying that it's actually talking to the shim: by comparing the hash of the shim's memory to one known to the VMM (say, compiled in) *** shim is a trusted loader; the VMM allows it to request any SID but the shim enforces the policy that it'll only start runnign the executables in the application definition *** thereafter, the VMM and shim isolate the application's execution environment, protecting the integrity of its register state and memory contents * Why isolation isn't enough: semantic attacks ** Same story as the HotSec '08 paper... * Securing the file system ** File contents *** Protected with encryption same as memory pages *** Persistent metadata (as in ASPLOS paper) ** File metadata *** Need to worry about this too -- guarantee that an application sees the files it's expecting, not some other files *** Trusted namespace daemon **** User-space component, trusted by all applications ***** Needs to run protected; easiest to implement as a special shim that runs its own code rather than executing an application **** Maintains mapping from file name to RID/RPN, loads metadata **** Needs to maintain a shadow copy of the directory hierarchy ***** Not enough to use a flat mapping (or store file name/hash in the Overshadow file header) because of directory rename and similar problems (see VPFS paper) **** Stores data in protected files, uses hash tree to ensure freshness ***** VMM persistently stores generation number or root hash *** Communicating with the namespace daemon **** Establish a shared memory buffer by mmapping a file in /overshadow/ipc, then pass messages through it (existing IPC code) **** No guarantee the daemon is on the other side of the connection. Need to bootstrap trust. ***** VMM provides random nonce to daemon via hypercall; daemon includes it in the shared memory buffer. Clients can verify this nonce via hypercall **** Frustrating implementation detail is that this requires *synchronous* IPC * Securing IPC ** General idea: send actual message through protected memory buffer, and send notification to check the buffer via OS mechanism *** uses trusted components to ensure security; reuses existing untrusted mechanisms to provide availability. *** different IPC mechanisms need different means for finding the buffer and sending the notification; need to generalize the implementation ** Process-to-process messages, e.g. signals, return values, etc. * Securing other miscellaneous services