corda/sgx-jvm
Chris Rankin 04a801e0cd Squashed commit of the following: (#50)
commit 9d8046e310efe860bb9d81e977a323f3905665c1
Author: Haitao Huang <4699115+haitaohuang@users.noreply.github.com>
Date:   Sat Sep 16 11:26:45 2017 -0500

    Check and handle signal interrupts in sockets

    Signed-off-by: Haitao Huang <4699115+haitaohuang@users.noreply.github.com>

commit 960ad91a4a8ec06020273a175471def37870fda6
Author: Haitao Huang <4699115+haitaohuang@users.noreply.github.com>
Date:   Sat Sep 16 11:27:35 2017 -0500

    Add error code in oal for invalid inputs

    Signed-off-by: Haitao Huang <4699115+haitaohuang@users.noreply.github.com>

commit e22c569335c1ec8d18f7df8105a68e9b9a82e691
Author: Li, Xun <xun.li@intel.com>
Date:   Wed Sep 20 10:51:18 2017 +0800

    Update libunwind for glibc 2.26 compatibility

    libunwind should include <signal.h> explicitly.
    glibc change sys/ucontext.h as a bug fix(https://sourceware.org/git/?p=glibc.git;a=commit;h=cfed8ece799b6e6540193a14b41d9de52dc3b08f)

    Signed-off-by: Li, Xun <xun.li@intel.com>

commit 9cda5c4774b2f4fc02fd031f98057cd88d14f2e0
Merge: 94c162c98 36918f071
Author: lzha101 <lili.z.zhang@intel.com>
Date:   Wed Sep 20 09:58:29 2017 +0800

    Merge pull request #165 from corda/chrisr3-stack-protector-fix

    Ensure trts_nsp.cpp is compiled without stack protection.

    Signed-off-by: Zhang Lili lili.z.zhang@intel.com

commit 36918f071fd29c86335b0cea0e072c3f08a51eae
Author: Chris Rankin <chris.rankin@r3.com>
Date:   Tue Sep 19 07:31:57 2017 +0000

    Ensure trts_nsp.cpp is compiled without stack protection.

    Signed-off-by: Chris Rankin <chris.rankin@r3.com>

commit 94c162c98bf95a034eadb41bfa6e6a35f410a0c8
Author: Kai Mast <kaimast@cs.cornell.edu>
Date:   Mon Sep 18 04:07:19 2017 -0400

    g++7 fixes (#148)

    Signed-off-by: Li, Xun<xun.li@intel.com>

commit 8a72fed8737dc8e331889e6530925fc5a0be2ea0
Merge: 2133df2d4 635e3a370
Author: Li Xun <xun.li@intel.com>
Date:   Mon Sep 18 15:58:10 2017 +0800

    Merge pull request #159 from corda/chrisr3-gcc7-fix

    Resolve GCC 7.1 warnings about deprecated throw(std::bad_alloc) in C++11.

    Signed-off-by: Li, Xun <xun.li@intel.com>

commit 635e3a37081ad3f773a0ff24c89f1e6094034d28
Author: Chris Rankin <chris.rankin@r3.com>
Date:   Wed Sep 13 10:31:11 2017 +0100

    Resolve warnings about deprecated throw(std::bad_alloc) in C++11.
2017-09-26 10:22:55 +01:00
..
avian Squashed commit of the following: (#41) 2017-09-13 10:09:17 +01:00
dependencies sgx: prepare for building in docker image on prod 2017-08-01 16:49:44 +02:00
hsm-tool sgx: Change HSM prod IP 2017-08-01 16:49:44 +02:00
jvm-enclave Register Kryo serializer for use inside the SGX enclave. (#23) 2017-08-15 12:05:32 +01:00
linux-sgx Squashed commit of the following: (#50) 2017-09-26 10:22:55 +01:00
linux-sgx-driver Recreate linux-sgx-driver as a subtree rather than a submodule. (#21) 2017-08-15 12:05:32 +01:00
noop-enclave sgx: More fiddling 2017-08-01 16:49:44 +02:00
Makefile Build javadocs for deterministic JVM. (#45) 2017-09-13 14:16:01 +01:00
README.md Build SGX against deterministic fork of OpenJDK8 (#16) 2017-07-19 13:29:47 +01:00
run_in_image.sh sgx: prod scripts 2017-08-01 16:49:44 +02:00
udev-cardreader.rules sgx: Add udev rule for cardreader 2017-08-01 16:49:44 +02:00
with_aesmd.sh sgx: More fiddling 2017-08-01 16:49:44 +02:00
with_hsm_simulator.sh sgx: prod scripts 2017-08-01 16:49:44 +02:00
with_isgx.sh sgx: prod scripts 2017-08-01 16:49:44 +02:00
with_ld_library_path.sh sgx: prod scripts 2017-08-01 16:49:44 +02:00

The build

Prerequisites

  • Install gcc/g++(6), autoconf, automake, ocaml, opendjk(8), libtool, python(2.7)
  • Make sure JAVA_HOME points to your OpenJDK 8 installation
  • Make sure CXX points to g++ (the project does NOT compile with other compilers like clang!)
  • If your hardware supports SGX and you want to use it directly you need to install and load the sgx kernel module (verify by running lsmod | grep isgx) and have the sgx service running (on a systemd setup verify by running systemctl status aesmd). Note that this is only required for actually running the binary, the build should work fine without.
  • The SGX SDK has a simulation mode that doesn't require hardware support. To use this edit sgx-jvm/jvm-enclave/common/CMakeLists.txt and change set(SGX_USE_HARDWARE TRUE) to FALSE

Toplevel Makefile targets

  • make will download all other dependencies and build the sgx_standalone_verify binary, residing at sgx-jvm/jvm-enclave/standalone/build/sgx\_standalone\_verify, as well as a JNI .so residing at sgx-jvm/jvm-enclave/jni/build/untrusted_corda_sgx.so
  • make clean will clean all build targets.
  • make distclean will clean all build targets and downloaded dependencies. Ordinarily you shouldn't need to run this.

Each project has its own build that may be run individually (check the toplevel Makefile to see how to invoke these)

At this point I suggest running make before reading further, it takes a while to download all dependencies.

Some reading

Before delving into the code it's strongly recommended to read up on SGX. Some links:

Corda SGX

The high level goal of the SGX work in Corda is to provide a secure way of verifying transactions. In order to do this we need to be able to run a JVM inside an enclave capable of running contract code. The design decision that contract verification code is without side-effects is imperative here.

The dream is to have a functioning JVM running inside SGX with as few limitations as possible. Clients would then be able to connect to the enclave, the TCB would attest that it is running the JVM image on secure hardware, after which the client can safely submit signed JARs for execution.

Corda would then be able to use this to submit contract code and transactions to run the contract code on.

This is the first iteration of the work, with a lot of limitations. The current JVM is based on Avian which can produce a standalone statically linked binary. The build statically links the enclavelet JAR into the static enclave binary (sgx-jvm/jvm-enclave/build/enclave/cordaenclave.so) which is then loaded and run by jvm/jvm-enclave/build/sgx\_experiments.

Breakdown of the build

The current SGX work in Corda is based on 4 semi-distinct projects:

  • The Avian JVM (in the sgx-jvm/avian subtree. Note this is our own fork)
  • The SGX linux sdk (in the sgx-jvm/linux-sgx subtree. Note this is our own fork)
  • The JVM enclave code itself, residing in sgx-jvm/jvm-enclave. This includes the untrusted and trusted part of the SGXified JVM, mostly C++.
  • Finally the Corda enclavelet. This is the JAR that will be loaded and run inside the enclave. (built by ./gradlew verify-enclave:jar

Avian

Avian has a code layout perfectly suited for SGX hacking. Each target platform (originally posix or windows) needs to implement a fairly straight-forward System interface providing OS-specific functionality like threading/synchronisation/memory/filesystem primitives. Check sgx-jvm/avian/src/system for code. We use this to implement an SGX "platform", which is basically a stripped down OS environment. Some additional #ifndef-ing was needed to strip some non-os-specific avian functionality that assumed the existence of a filesystem or networking. This work is maintained in a private fork, it is instructive to read through the diff, see https://bitbucket.org/R3-CEV/avian-sgx/.

SGX SDK

There are some modifications in the upstream SGX SDK that we require to run the JVM. An example would be the ability to make the heap executable for JIT compilation, or exposing hooks into malloc to detect OOM conditions. All of these should be mergeable, but we maintain a fork to speed up development on our side.

Corda Enclavelet

This is the JAR that will be run inside the enclave. Check verify-enclave/src/../Enclavelet.kt for the code.

Currently the JAR is not loaded at runtime, but is rather embedded statically into the enclave itself using Avian's binaryToObject utility. This basically does an objcopy and lets the linker do the embedding later. This will later be changed to dynamic loading of signed JARs.

The JVM enclave

This consists of two parts: the untrusted code that loads the enclave and provides the OCALLs (see sgx-jvm/jvm-enclave/main.cpp), and the trusted enclave that constructs the JVM using JNI and runs the enclavelet class. (see sgx-jvm/jvm-enclave/enclave/enclave.cpp).

Dynamic loading, linkage

Avian by default loads some JVM specific code dynamically, and looks up these symbols at runtime. We link these symbols statically and provide a simple binary search lookup at runtime to find the symbols corresponding to symbol name strings. To see how this is done check sgx-jvm/jvm-enclave/enclave/gen_dispatch_table.py.

Avian also statically links against system libraries providing usual OS functionality. We deal with this by stubbing all of the undefined symbols and implementing/mocking them as needed. The stub generation simply greps for undefined symbols when running make, check sgx-jvm/jvm-enclave/enclave/gen-stubsyms.sh for this. The implemented/mocked OS functions reside in sgx-jvm/jvm-enclave/enclave/os_support.cpp