Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Integrations/ita] Add RA-TLS/SecretProv libs for Intel Trust Authority #59

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Integrations/ita/ra_tls_ita/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/build
/gramine
.history/
.vscode/
*.diff
*.patch
.cache/
185 changes: 185 additions & 0 deletions Integrations/ita/ra_tls_ita/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
## Intel Trust Authority (ITA)

**NOTE**: This document assumes familiarity with SGX attestation protocols and
RA-TLS/Secret Provisioning libraries shipped with Gramine. Please refer to
Gramine documentation for details:
- https://gramine.readthedocs.io/en/stable/attestation.html
- https://gramine.readthedocs.io/en/stable/glossary.html
- https://gramine.readthedocs.io/en/stable/sgx-intro.html#sgx-terminology

**DISCLAIMER**: This version was tested with Gramine v1.5 and ITA REST API version
`v1.0.0`.

---

[Intel Trust Authority](https://trustauthority.intel.com/) is a suite of trust
and security services that provides customers with assurance that their apps and
data are protected on the platform of their choice, including multiple cloud,
edge, and on-premises environments.

Similarly to the Intel-developed EPID protocol, the remote verifier based
on the ITA protocol needs to contact the ITA attestation provider each time it
wishes to attest an enclave. An enclave sends DCAP-formatted SGX quotes to the
client/verifier who will forward them to the ITA attestation provider to check
the enclave's validity and receive back the set of claims describing this
enclave.

For more information on ITA, refer to official documentation:
- https://www.intel.com/content/www/us/en/security/trust-authority.html
- https://portal.trustauthority.intel.com/workspace/documentation

### Gramine manifest file

Because ITA attestation uses DCAP-formatted SGX quotes, the manifest in Gramine
must contain the following line:
```
sgx.remote_attestation = "dcap"
```

### RA-TLS library: `ra_tls_verify_ita.so`

Similarly to e.g. `ra_tls_verify_epid.so`, the `ra_tls_verify_ita.so` library
contains the verification callback that should be registered with the TLS
library during verification of the TLS certificate. It verifies the RA-TLS
certificate and the SGX quote by sending it to the Intel Trust Authority (ITA)
provider and retrieving the attestation response (the JWT) from it. This
library is *not* thread-safe.

Note that the JWT's signature can be verified using one of the set of JSON Web
Keys (JWKs). The RA-TLS library retrieves this set of JWKs together with
retrieving the JWT (this eager fetching of JWKs guarantees the freshness of
these keys).

The library verifies the following set of claims in the received JWT:
- `ver` (JWT schema version, expected to be "1.0.0")
- `attester_type` (expected to be "SGX")
- `exp` (expiration time of JWT)
- `nbf` (not-before time of JWT)
- `sgx_is_debuggable` (verified using `RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE`)
- `sgx_mrenclave` (verified against `RA_TLS_MRENCLAVE`)
- `sgx_mrsigner` (verified against `RA_TLS_MRSIGNER`)
- `sgx_isvprodid` (verified against `RA_TLS_ISV_PROD_ID`)
- `sgx_isvsvn` (verified against `RA_TLS_ISV_SVN`)
- `sgx_report_data` (verified to contain the hash of the RA-TLS public key)

The library uses the same [SGX-specific environment variables as
`ra_tls_verify_epid.so`](https://gramine.readthedocs.io/en/stable/attestation.html#ra-tls-verify-epid-so)
and ignores the EPID-specific environment variables. Similarly to the EPID
version, instead of using environment variables, the four SGX measurements may
be verified via a user-specified callback registered via
`ra_tls_set_measurement_callback()`.

The library uses the following ITA-specific environment variables:

- `RA_TLS_ITA_PROVIDER_URL` (mandatory) -- URL for ITA provider's REST API
endpoints.
- `RA_TLS_ITA_PROVIDER_API_VERSION` (optional) -- version of the ITA
provider's REST API `attest` endpoint. If not specified, the default
hard-coded version `v1` is used.
- `RA_TLS_ITA_API_KEY` (mandatory) -- API key for ITA provider's API endpoint
access.
- `RA_TLS_ITA_PORTAL_URL` (mandatory) -- URL for ITA provider's JWKs download.

Note that the library does *not* use the following SGX-enclave-status
environment variables: `RA_TLS_ALLOW_OUTDATED_TCB_INSECURE`,
`RA_TLS_ALLOW_HW_CONFIG_NEEDED` and `RA_TLS_ALLOW_SW_HARDENING_NEEDED`. This is
because ITA will only generate a JWT for the SGX enclave if the enclave's TCB
level matches the "TCB baseline" specified in the used ITA policy. In other
words, ITA takes the responsibility away from the Gramine user and decides about
the allowed security status of the SGX enclave based on its policy and not based
on the aforementioned RA-TLS environment variables.

However, the library uses the `RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE` environment
variable because typically ITA policies allow debug enclaves.

The library sets the following ITA-specific environment variables:

- `RA_TLS_ITA_JWT` -- contains the raw ITA JWT (JSON object).
- `RA_TLS_ITA_SET_OF_JWKS` -- contains the raw set of JWKs (JSON object).

### Secret Provisioning library: `secret_prov_verify_ita.so`

Similarly to `secret_prov_verify_epid.so`, this library is used in
secret-provisioning services. The only difference is that this library uses ITA
based RA-TLS flows underneath.

The library sets the same environment variables as `ra_tls_verify_ita.so`,
namely `RA_TLS_ITA_JWT` and `RA_TLS_ita_SET_OF_JWKS`.

### Building ITA libraries

The only prerequisite is that Gramine v1.5 must be installed on the system.

To build the `ra_tls_verify_ita.so` and `secret_prov_verify_ita.so` libraries,
we use the meson build system:
```sh
meson setup build/ --buildtype=release
ninja -C build/
sudo ninja -C build/ install
```

This installs the two libraries under a system-wide path. This path should be
added to the manifest file of an application that wishes to use ITA libraries
(typically manifests already contain this path).

Similarly to EPID- and DCAP-based RA-TLS/Secret Prov libraries shipped with
Gramine, the ITA-based libraries are minimized and statically linked with all
dependencies except libc ones.

### Testing ITA libraries

The ITA libraries can be tested with the
[`ra-tls-mbedtls`](https://github.com/gramineproject/gramine/tree/master/CI-Examples/ra-tls-mbedtls)
and
[`ra-tls-secret-prov`](https://github.com/gramineproject/gramine/tree/master/CI-Examples/ra-tls-secret-prov)
examples available in Gramine.

To be able to run these tests, the machine must run on the SGX enabled host, with
access to the ITA attestation provider service.

For this, we provide a patch that should be applied on top of Gramine v1.5 repo:
```sh
git clone --depth 1 --branch v1.5 https://github.com/gramineproject/gramine.git
cd gramine/
git apply ../helpers/gramine-v1.5-ci-examples.patch
```

To test the `ra-tls-mbedtls` example, cd to its directory and run:
```sh
make clean
make app ita RA_TYPE=dcap

gramine-sgx ./server &

RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE=1 \
RA_TLS_ITA_PROVIDER_URL="https://api.trustauthority.intel.com" \
RA_TLS_ITA_PORTAL_URL="https://portal.trustauthority.intel.com" \
RA_TLS_ITA_API_KEY=<ITA API key> \
RA_TLS_MRENCLAVE=<MRENCLAVE of the server enclave> \
RA_TLS_MRSIGNER=<MRSIGNER of the server enclave> \
RA_TLS_ISV_PROD_ID=<ISV_PROD_ID of the server enclave> \
RA_TLS_ISV_SVN=<ISV_SVN of the server enclave> \
./client ita

# client will successfully connect to the server via RA-TLS/ITA flows
kill %%
```

To test the `ra-tls-secret-prov` example, cd to its directory and run:
```sh
make clean
make app ita RA_TYPE=dcap

# test encrypted files client (other examples can be tested similarly)
cd secret_prov_pf

RA_TLS_ALLOW_DEBUG_ENCLAVE_INSECURE=1 \
RA_TLS_ITA_PROVIDER_URL="https://api.trustauthority.intel.com" \
RA_TLS_ITA_PORTAL_URL="https://portal.trustauthority.intel.com" \
RA_TLS_ITA_API_KEY=<ITA API key> \
./server_ita wrap_key &

gramine-sgx ./client

kill %%
```
177 changes: 177 additions & 0 deletions Integrations/ita/ra_tls_ita/helpers/gramine-v1.5-ci-examples.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
diff --git a/CI-Examples/ra-tls-mbedtls/Makefile b/CI-Examples/ra-tls-mbedtls/Makefile
index 4adc0ee..81b2d6f 100644
--- a/CI-Examples/ra-tls-mbedtls/Makefile
+++ b/CI-Examples/ra-tls-mbedtls/Makefile
@@ -27,6 +27,9 @@ epid: client_epid.manifest.sgx client_epid.sig
.PHONY: dcap
dcap: client_dcap.manifest.sgx client_dcap.sig

+.PHONY: ita
+ita: client_ita.manifest.sgx client_ita.sig
+
############################# SSL DATA DEPENDENCY #############################

# SSL data: key and x.509 self-signed certificate
@@ -107,6 +110,23 @@ sgx_sign_client_epid: client_epid.manifest client
--manifest $< \
--output $<.sgx

+########################### CLIENT (ita) MANIFEST #############################
+
+client_ita.manifest: client.manifest.template
+ gramine-manifest \
+ -Dlog_level=$(GRAMINE_LOG_LEVEL) \
+ -Darch_libdir=$(ARCH_LIBDIR) \
+ $< >$@
+
+client_ita.manifest.sgx client_ita.sig: sgx_sign_client_ita
+ @:
+
+.INTERMEDIATE: sgx_sign_client_ita
+sgx_sign_client_ita: client_ita.manifest client
+ gramine-sgx-sign \
+ --manifest $< \
+ --output $<.sgx
+
############################### SGX CHECKS FOR CI #############################

.PHONY: check_epid
@@ -149,6 +169,26 @@ check_dcap_fail: app dcap
./client dcap && exit 1 || echo "[ Success 1/1 ]"; \
kill -9 $$SERVER_ID

+.PHONY: check_ita
+check_ita: app ita
+ gramine-sgx server >/dev/null & SERVER_ID=$$!; \
+ ../../scripts/wait_for_server 60 127.0.0.1 4433; \
+ ./client ita > OUTPUT; \
+ ./client ita 0 0 0 0 >> OUTPUT; \
+ kill -9 $$SERVER_ID
+ @grep -q "using default SGX-measurement verification callback" OUTPUT && echo "[ Success 1/4 ]"
+ @grep -q "using our own SGX-measurement verification callback" OUTPUT && echo "[ Success 2/4 ]"
+ @grep -q "Verifying peer X.509 certificate... ok" OUTPUT && echo "[ Success 3/4 ]"
+ @(exit `grep -c "failed" "OUTPUT"`) && echo "[ Success 4/4 ]"
+ @rm OUTPUT
+
+.PHONY: check_ita_fail
+check_ita_fail: app ita
+ gramine-sgx server --test-malicious-quote >/dev/null & SERVER_ID=$$!; \
+ ../../scripts/wait_for_server 60 127.0.0.1 4433; \
+ ./client ita && exit 1 || echo "[ Success 1/1 ]"; \
+ kill -9 $$SERVER_ID
+
################################## CLEANUP ####################################

.PHONY: clean
diff --git a/CI-Examples/ra-tls-mbedtls/src/client.c b/CI-Examples/ra-tls-mbedtls/src/client.c
index 6b7d056..b8decbd 100644
--- a/CI-Examples/ra-tls-mbedtls/src/client.c
+++ b/CI-Examples/ra-tls-mbedtls/src/client.c
@@ -165,9 +165,9 @@ int main(int argc, char** argv) {
mbedtls_x509_crt_init(&cacert);
mbedtls_entropy_init(&entropy);

- if (argc < 2 ||
- (strcmp(argv[1], "native") && strcmp(argv[1], "epid") && strcmp(argv[1], "dcap"))) {
- mbedtls_printf("USAGE: %s native|epid|dcap [SGX measurements]\n", argv[0]);
+ if (argc < 2 || (strcmp(argv[1], "native") && strcmp(argv[1], "epid") &&
+ strcmp(argv[1], "dcap") && strcmp(argv[1], "ita"))) {
+ mbedtls_printf("USAGE: %s native|epid|dcap|ita [SGX measurements]\n", argv[0]);
return 1;
}

@@ -210,6 +210,13 @@ int main(int argc, char** argv) {
return 1;
}
}
+ } else if (!strcmp(argv[1], "ita")) {
+ ra_tls_verify_lib = dlopen("libra_tls_verify_ita.so", RTLD_LAZY);
+ if (!ra_tls_verify_lib) {
+ mbedtls_printf("%s\n", dlerror());
+ mbedtls_printf("User requested RA-TLS verification with ita but cannot find lib\n");
+ return 1;
+ }
}

if (ra_tls_verify_lib) {
diff --git a/CI-Examples/ra-tls-secret-prov/.gitignore b/CI-Examples/ra-tls-secret-prov/.gitignore
index cc4e300..a125fa6 100644
--- a/CI-Examples/ra-tls-secret-prov/.gitignore
+++ b/CI-Examples/ra-tls-secret-prov/.gitignore
@@ -2,12 +2,15 @@
/secret_prov/client
/secret_prov/server_epid
/secret_prov/server_dcap
+/secret_prov/server_ita
/secret_prov_minimal/client
/secret_prov_minimal/server_epid
/secret_prov_minimal/server_dcap
+/secret_prov_minimal/server_ita
/secret_prov_pf/client
/secret_prov_pf/server_epid
/secret_prov_pf/server_dcap
+/secret_prov_pf/server_ita
/secret_prov_pf/wrap_key
/secret_prov_pf/enc_files/input.txt

diff --git a/CI-Examples/ra-tls-secret-prov/Makefile b/CI-Examples/ra-tls-secret-prov/Makefile
index 2780651..96a6094 100644
--- a/CI-Examples/ra-tls-secret-prov/Makefile
+++ b/CI-Examples/ra-tls-secret-prov/Makefile
@@ -36,6 +36,10 @@ epid: ssl/server.crt secret_prov_minimal/server_epid secret_prov/server_epid sec
dcap: ssl/server.crt secret_prov_minimal/server_dcap secret_prov/server_dcap secret_prov_pf/server_dcap \
secret_prov_pf/wrap_key secret_prov_pf/enc_files/input.txt

+.PHONY: ita
+ita: ssl/server.crt secret_prov_minimal/server_ita secret_prov/server_ita secret_prov_pf/server_ita \
+ secret_prov_pf/wrap_key secret_prov_pf/enc_files/input.txt
+
############################# SSL DATA DEPENDENCY #############################

# SSL data: key and x.509 self-signed certificate
@@ -60,6 +64,9 @@ LDFLAGS += -Wl,--enable-new-dtags $(shell pkg-config --libs secret_prov_gramine)
%/server_dcap: %/server.c
$(CC) $< $(CFLAGS) $(LDFLAGS) -Wl,--no-as-needed -lsgx_urts -lsecret_prov_verify_dcap -pthread -o $@

+%/server_ita: %/server.c
+ $(CC) $< $(CFLAGS) $(LDFLAGS) -lsecret_prov_verify_ita -pthread -o $@
+
secret_prov/client: secret_prov/client.c
$(CC) $< $(CFLAGS) $(LDFLAGS) -lsecret_prov_attest -o $@

@@ -213,6 +220,35 @@ check_dcap: app dcap

@rm OUTPUT

+.PHONY: check_ita
+check_ita: app ita
+ # secret_prov_minimal
+ cd secret_prov_minimal; \
+ ./server_ita >/dev/null & SERVER_ID=$$!; \
+ ../../../scripts/wait_for_server 60 127.0.0.1 4433; \
+ gramine-sgx client > ../OUTPUT; \
+ kill -9 $$SERVER_ID;
+ @grep -E "Received secret = 'A_SIMPLE_SECRET'" OUTPUT && echo "[ Success 1/4 ]"
+
+ # secret_prov
+ cd secret_prov; \
+ ./server_ita >/dev/null & SERVER_ID=$$!; \
+ ../../../scripts/wait_for_server 60 127.0.0.1 4433; \
+ gramine-sgx client > ../OUTPUT; \
+ kill -9 $$SERVER_ID;
+ @grep -E "Received secret1 = 'FIRST_SECRET', secret2 = '42'" OUTPUT && echo "[ Success 2/4 ]"
+
+ # secret_prov_pf
+ cd secret_prov_pf; \
+ ./server_ita wrap_key >/dev/null & SERVER_ID=$$!; \
+ ../../../scripts/wait_for_server 60 127.0.0.1 4433; \
+ gramine-sgx client > ../OUTPUT; \
+ kill -9 $$SERVER_ID;
+ @grep -E "\[parent\] Read from protected file: 'helloworld'" OUTPUT && echo "[ Success 3/4 ]"
+ @grep -E "\[child\] Read from protected file: 'helloworld'" OUTPUT && echo "[ Success 4/4 ]"
+
+ @rm OUTPUT
+
################################## CLEANUP ####################################

.PHONY: clean
Loading