-
Notifications
You must be signed in to change notification settings - Fork 11
Mock Mode
Conclave provides a number of different modes when building your enclave, supporting different stages of the development cycle. Release, debug, and simulation modes require a Linux environment to run. This does not prevent running a simulation enclave on macOS or Windows if you load and run your project in a Docker container, but for convenience, it is useful to be able to run your enclave code directly within the host environment. In addition, the build time for simulation, debug, and release enclaves can be quite high.
With mock mode, the enclave class runs in the same JVM as the host, so interactions between the enclave and host are just regular function calls. You can expect very short build times, step through using a debugger and enjoy the regular Java development experience.
Note
To debug your host application in mock mode from IntelliJ, find the :host:run
task in the Gradle menu, add the -PenclaveMode=mock
argument to the run configuration, and then run the task in debug mode.
The mock mode can be used in two different ways, depending on whether the enclave is being loaded from outside or inside the enclave module.
Outside the enclave module, The mode can be set when adding a Gradle dependency, just like any other mode:
dependencies {
runtimeOnly project(path: ":enclave", configuration: "mock")
}
See Setting the enclave mode for more details.
When creating an EnclaveHost
inside the enclave module,
Conclave will automatically create it in mock mode.
This means any tests you define in the enclave module will automatically use mock mode - you can write your tests to load
and call the enclave without having to explicitly configure a mock enclave.
For tests to use any other mode, they must be defined outside the enclave module, for example in the host.
Conclave looks in two places for the enclave class when loading an enclave from the host. Firstly, it looks on the current classpath. If the enclave class is present in the classpath, it will assume a mock configuration and load the enclave code directly. Secondly, it looks in the resources for a JAR file that contains a simulation, debug or release enclave. If that is present, it is unpacked and loaded.
If the enclave class is on the classpath and the enclave JAR file is present, the host will throw an exception stating that multiple enclave classes have been found. To avoid this, you need to carefully configure the dependencies in your host project to ensure only a single enclave is present.
In most cases, you do not require the enclave classes within the host project. So, all you need to do is set the
enclave project as a runtimeOnly
dependency. This will then work for all enclave configurations:
runtimeOnly project(path: ":enclave", configuration: mode)
If, however, you do need to access the enclave class in your host project in mock mode via the the EnclaveHost.mockEnclave
property then you will need to conditionally depend on the enclave project at compile or implementation time by
including this in your host build.gradle
:
if (mode == "mock") {
implementation project(path: ":enclave", configuration: "mock")
} else {
runtimeOnly project(path: ":enclave", configuration: mode)
}
!!! info Note that within the enclave project the enclave class is always present on the classpath. This means that all tests defined within the enclave project always use mock mode.
When using mock mode, the host provides access to the enclave instance via the
EnclaveHost.mockEnclave
property. If you
want to look at the internal state of your enclave, you can cast this property to your actual enclave class type.
ReverseEnclave reverseEnclave = (ReverseEnclave)mockHost.getMockEnclave();
Note
The EnclaveHost.mockEnclave
property can only be used with mock enclaves. The host does not have access to internal enclave state for any other enclave type. If you attempt to access the property on a non-mock enclave then IllegalStateException
will be thrown.
When you build an enclave in release, debug mode, or simulation mode, there are certain environmental parameters that are defined by the trusted computing base and the Conclave configuration.
In mock mode, instead of being defined by the platform, these parameters are defined using the
MockConfiguration
class which is subsequently passed to EnclaveHost.load
.
This class can be used to configure these parameters for use
when the mock enclave is loaded. This is useful to allow test cases to be written for checking correct enclave operation around
version increments and rollbacks.
The MockConfiguration
class allows the configuration of
the following properties. The table below describes each property and
shows the SGX equivalent parameter for information.
Property | SGX Equivalent | Allowed values | Default Value | Description |
---|---|---|---|---|
codeHash | MRENCLAVE | 32 byte array | SHA256(enclave class name) | Specifies an array of bytes for the enclave code hash measurement. |
codeSigningKeyHash | MRSIGNER | 32 byte array | 32 zero bytes | Specifies an array of bytes to use as a hash of the public key used to sign the enclave. The mock enclave will create a public/private key pair based on this value. |
productID | ISVProdId | 1-65535 | 1 | The mock product ID of the enclave, is used to uniquely identify enclaves signed with the same signing key. |
revocationLevel | ISVSVN | 0-65534 | 0 | The mock revocation level of the enclave. |
tcbLevel | CPUSVN | 1-65535 | 1 | A mock version number that defines the TCB level, or version number of the TCB. This is equivalent to the SGX CPUSVN but because Conclave uses an integer, the TCBLevel is ordered allowing for easy testing of TCB recovery. |
If you do not provide a MockConfiguration
when loading
a mock enclave, the default values are used.
If you want to specify your own MockConfiguration
, you can configure these properties when loading the
enclave via the host using code similar to this:
MockConfiguration config = new MockConfiguration();
config.setProductID(2);
config.setTcbLevel(3);
config.setCodeSigningKeyHash(SHA256Hash.parse("1234567890123456789012345678901234567890123456789012345678901234"));
EnclaveHost mockHost = EnclaveHost.load("com.r3.conclave.sample.enclave.ReverseEnclave", config);