How do you know the
EnclaveInstanceInfo you've got is for the enclave you really intend to interact with? In normal
client/server programming you connect to a host using some sort of identity, like a domain name or IP address. TLS
is used to ensure the server that picks up is the rightful owner of the domain name you intended to connect to. In
enclave programming the location of the enclave might not matter much because the host is untrusted. Instead, you have
to verify what is running, rather than where it's running.
The domain name of the server can still be important in some applications, in which case you should still use TLS in addition to enclave constraints.
One way to do this is by inspecting the properties on the
EnclaveInstanceInfo object and hard-coding some logic. That
works fine, but testing an
EnclaveInstanceInfo is a common pattern in enclave programming, so we provide an API to
do it for you.
EnclaveConstraint class takes an
performs some matching against it. A constraint object can be built in code, or it can be loaded from a small domain
specific language encoded as a one-line string. The string form is helpful if you anticipate frequent upgrades that
should be whitelisted or other frequent changes to the acceptable enclave, as it can be easily put into a
configuration file, JSON, XML or command line flags.
The constraint lets you specify:
- Acceptable code hashes (measurements)
- Acceptable signing public keys
- The minimum revocation level
- The product ID
- The security level of the instance:
- The maximum age of the attestation in ISO-8601 duration format
If you specify a signing public key then you must also specify the product ID, otherwise if the organisation that created the enclave makes a second different kind of enclave in the future, a malicious host might connect you with the wrong one. If the input/output commands are similar then a confusion attack could be opened up. That's why you must always specify the product ID.
The simplest possible string-form constraint looks like this:
It says "accept exactly one program, with that measurement hash". In this case the value came from the output of the build process as shown above. This is useful when you neither trust the author nor the host of the enclave, and want to audit the source code and then reproduce the build.
Often that's too rigid. We trust the developer of the enclave, just not the host. In that case we'll accept any enclave signed by the developer's public key. We can express that by listing code signing key hashes, like this:
When constraining to a signing key we must also specify the product ID, because a key can be used to sign more than one product.
As you can see from the above code, the enclave constraint is passed into the client via a command line flag:
Replace the signing key in the snippet above with the enclave signer hash that was printed when you built the enclave.
The above constraint says that any enclave (even if run in simulation mode) signed by this hash of a code signing key
with product ID of 1 is acceptable. Obviously in a real app, you would remove the part that says
it's convenient to have this whilst developing.
EnclaveConstraint.check compares the
EnclaveInstanceInfo against the constraint and
InvalidEnclaveException) if it doesn't
match. This check is done automatically by
EnclaveClient.start when using
If needed, more than one key hash could be added to the list of enclave constraints (e.g. if simulation and debug modes use a distinct key from release mode). The enclave is accepted if one key hash matches.
If you are building an enclave in mock mode then the enclave reports it is using a signing key hash consisting of all zeros. If you want to allow a mock enclave to pass the constraint check then you need to include this dummy signing key in your constraint:
It is also possible to specify a maximum age for the attestation using the EXPIRE keyword:
When specified, this will cause the check to fail if the timestamp within the attestation object indicates an age older than the specified duration. If no period is specified then no expiry check will be applied. The age string uses the ISO-8601 duration format. The above example is enforcing a maximum age of 6 months, 2 weeks and 5 days.