Protected files (PF) are a new type of file that can be specified in
the manifest (SGX only). They are encrypted on disk and transparently
decrypted when accessed by the Graphene payload.
Other features:
- data is integrity protected (tamper resistance)
- file swap protection (a PF can only be accessed when in a specific path)
- transparency (Graphene payload sees PFs as regular files, no need to modify
the payload)
See Linux-SGX/protected-files directory for implementation. PF format is
based on protected files from the SGX SDK:
https://github.com/intel/linux-sgx/tree/master/sdk/protected_fs
The following new manifest elements are added:
sgx.protected_files_key = <16-byte hex value>
sgx.protected_files.<name> = file:<host path>
sgx.protected_files_key specifies the encryption key and is only a temporary
implementation. This key should be provisioned with local/remote attestation
in the future.
Paths specifying PF entries can be files or directories. If a directory is
specified, all files/directories within are registered as protected
recursively (and are expected to be encrypted in the PF format).
Linux-SGX/tools directory contains the pf_crypt utility that converts files
to/from the protected format.
Previously, Graphene simply forwarded SIGPIPE generated by the host to
LibOS/app. Unfortunately, SIGPIPE generation is a process-wide feature
and there is no portable way to restrict it only to a subset of pipes,
UNIX domain sockets, etc. This led to sporadic Graphene failures
because Graphene's internal use of pipes and sockets may result in an
unexpected (to application) SIGPIPE.
This commit removes the forwarding of SIGPIPE. Instead, PALs explicitly
ignore SIGPIPE. This forces the host to return EPIPE error code, which
is checked only on a subset of LibOS handles (the ones created by the
app), and if required, LibOS generates a SIGPIPE for the application.
While adding this logic, the whole PAL exception code was refactored,
both in Linux and Linux-SGX. Tests for SIGPIPE are now enabled for
both Linux and Linux-SGX PALs.
Previously, lib_SSLRead() and lib_SSLWrite() returned PAL_ERROR_DENIED
on any error, even on benign try-again errors from mbedTLS. This led
to LibOS returning EACCES to the application which doesn't expect such
error code. This commit converts benign try-again errors into
corresponding PAL_ERROR_TRYAGAIN errors.
Linux-SGX PAL uses mbedTLS sessions for encrypted IPC. This requires
a TLS handshake on pipe/socketpair creation. Previously, if the pipe
was created with O_NONBLOCK, read/write callbacks for mbedTLS session
could return EAGAIN or EWOULDBLOCK if the pipe was occupied. We
forgot to check for these error codes, and TLS handshake failed as a
result on the first EAGAIN/EWOULDBLOCK (detected on NodeJS example).
These error codes are actually benign, and Graphene should simply
ask mbedTLS to retry read/write.
mbedTLS configuration used in Graphene is not thread-safe (because
this would require the use of a threading library like pthread which
is not possible in the LibOS/Pal layers). However, some mbedTLS
functions use shared state, in particular TLS context initialization
functions. This led to data races during encrypted-pipe creation,
since it requires two threads performing a TLS handshake. This commit
refactors TLS init into SSLInit (not thread-safe) and SSLHandshake
(thread-safe) and adds spinlocks around SSLInit to protect the racy
mbedTLS logic.
Previously, Linux-SGX PAL did not encrypt pipe/socketpair
communication (only process checkpoint send/receive was encrypted).
This commit encrypts all pipe/socketpair IPC between threads of
the same enclave and between enclave processes. In particular, all
offsprings of the "first" enclave inherit the same master key and
derive IPC session keys from this master key based on pipe name.
When two pipe/socketpair endpoints are first created, they establish
a TLS-PSK session via intra-enclave handshake (requires a spawn of
an intermediate enclave thread). During clone/fork/exec, endpoints'
TLS contexts are serialized and sent to the child that deserializes
them (using mbedtls_ssl_context_{save,load} functions).
Note that multicast pipes (with more than two communicating entities)
are not supported since TLS protocol doesn't support it.
This commit modifies the PAL `SendHandle` test to correctly test
pipe communication, as well as adds the LibOS `pipe` test.
Previous version of mbedTLS used in Graphene (v2.16.3) is old and
does not have TLS-context serialization functionality. This commit
updates mbedTLS to v2.21.0 (released February 2020); this version
has mbedtls_ssl_session_save() and mbedtls_ssl_session_load() for
TLS context serialization. These functions will be needed for IPC
encryption.
Previously, Graphene with SGX performed self-remote attestation
by retrieving the SGX quote from the Quoting Enclave, sending it
to the Intel Attestation Service via Curl (in an HTTPS request),
and parsing the received from IAS remote-attestation certificate.
This self-attestation functionality is meaningless and is removed.
Moreover, since EPID-based remote attestation requires client key
(Ocp-Apim-Subscription-Key), and this key must be kept secret,
specifying it in the Graphene manifest (as was done previously) is
insecure. Therefore, the whole remote attestation functionality is
moved out of Graphene and to another trusted party (or to the app
on top of Graphene). Only the SGX quote retrieval from the Quoting
Enclave is kept in Graphene.
Previously, Graphene-SGX did not protect send/recv of checkpoint from
parent to child. This leaked all memory contents of the parent process.
This commit adds TLS-PSK (TLS with Pre-Shared Key) wrapper for process
communication. Graphene-SGX already has the logic for SGX-based local
attestation and generation of the shared key for each parent <-> child
communication channel via Diffie–Hellman key exchange. This commit
uses this pre-shared key to create an mbedTLS-based session based on
UNIX domain socketpair (parent.process.stream <-> child.process.stream).
_DkStreamSecure{Init,Free,Read,Write} internal Linux-SGX PAL functions
are added and used during child process creation and sending of the
parent-generated checkpoint. These functions are backed by crypto-layer
lib_SSL{Init,Free,Read,Write} functions which in turn use mbedTLS.
Configuration of mbedTLS is expanded to support TLS-PSK; note that for
entropy source we use only rdrand instruction inside SGX enclave (i.e.,
no untrusted host-platform sources of entropy). The only ciphersuite
currently supported for IPC is MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256.
This commit adds protection only for checkpoint IPC. After the checkpoint
is sent/received, the parent/child processes downgrade their sockets to
plain non-secure ones (by disabling TLS). This is done because child
may spawn a grandchild that also wants to communicate with grandparent,
but it is impossible for multiple processes to share same TLS context.
Additionally, this commit sanitizes "process" PAL handles during send-
handle checkpoint send (via DkSendHandle): shared key and TLS context
are zeroed out.
This is the minimalistic implementation of the remote attestation
framework. The framework conducts the following steps during
start-up to verify the authenticity of the SGX platform:
1. Connect to aesmd service to retrieve platform info (targetinfo)
of the Quoting Enclave (QE) before enclave creation.
2. Prepare the SGX report inside enclave (during initialization):
- Read SPID (service provider ID) from sgx.ra_client_spid in
manifest.
- Get an SGX report for local attestation to QE.
- Generate a random 16-byte nonce for freshness.
- Perform an OCALL for retrieving the quote.
3. Gather attestation data (QE report, QE quote, IAS report, signature,
certificate chain) outside of enclave:
- Connect to aesmd to retrieve the QE quote; aesmd also returns
QE report.
- Connect to Intel Attestation Service using curl. A client
subscription key (specified via sgx.ra_client_key in manifest)
is required to authenticate the HTTPS connection.
- Get the IAS report, signature, and certificate chain from IAS.
Print out the attestation result.
- Return all this attestation data back to the enclave.
* Fix a bug where configuration error ends up doing a huge allocation, rather than catching the error. Add some documentation to the slabmgr code.
* Add a unit test and some documentation to answer the question in issue #107. I can't see how offset and map_start would end up being different.
* Rewrite of SGX file_map to remove TOCTTTOU now passes all unit tests
* Apply a similar fix to file_read.
* Factor complicated verification code into a common helper routine.
* Adjust the memory copying strategy so that all bits in the returned buffed are exactly the same bits as verified in the trusted, scratch buffer.
* Fixing the TOCTOU issue in file checking
* Adding comments for load_trusted_file() and copy_and_check_trusted_file(); Deprecate the old design
* Documenting the file checking mechanism
* Update all headers to reflect LGPL license.
* Add submodule for gcc test inputs
* Add submodule for lmbench-2.5
* Fix Travis build with submodules
* Migrate driver to sub repository
* Migrate driver to sub repository
Replace the atomics implementation.
* Change the PAL Semaphore to a Mutex, and fix some issues in the Mutex implementations
* Tweak the layout of a PAL Handle
* Rework some of the IPC helper synchronization
* Taking out waitpid03 - it is flaky, even on the commit where it was added to the PASSED list.
Replace the directory cache implementation.
* Fix unix domain socket lookup.
* Fix a bug in the getdents EINVAL case
* remove profiling code in dcache.c; cleaning up some style issues
* adding a note to the recursive path_lookupat() code
* remove a few compilation warnings
* Apply Chia-Che's suggested fixes; add more now-passing cases to LTP nice list.
* Ref counting bug for /proc/self/fd/. Document and implement expected behavior in relevant helper function.
* Remove the Linux linked list implementation, replace with a new implementation that adds some type-checking that list pointers (heads) and entries/nodes match.
* Fix the debug build by consolidating assertions into one header
* Several memory allocation fixes, primarily motivated by the fact that the Diffie-Hellman implementation in mbedtls is sensitive to misaligned allocations. All malloc's are now 16-byte aligned. This PR has several other points where remalloc was used instead of realloc, or memory needed to be zeroed upon allocation. Finally, this PR also standardizes the definition of assert across layers, so that code in the lib directory can both use assertions and link properly in the PAL and shim.