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

[RA-TLS ITA] Implement Intel Trust Authority plugin #73

Closed
dimakuv opened this issue Jan 15, 2024 · 1 comment · Fixed by #75
Closed

[RA-TLS ITA] Implement Intel Trust Authority plugin #73

dimakuv opened this issue Jan 15, 2024 · 1 comment · Fixed by #75

Comments

@dimakuv
Copy link

dimakuv commented Jan 15, 2024

The first attempt to implement ITA (Intel Trust Authority) was done in this PR: #59.

The PR takes the already-existing MAA (Microsoft Azure Attestation) plugin and builds on it. This is possible because ITA is very similar to MAA.

Below is the git-diff between the already-existing MAA plugin and the added-by-pr59 ITA plugin (I removed the README and other tiny diffs):

diff --git a/contrib/Integrations/azure/ra_tls_maa/helpers/gramine-v1.5-ci-examples.patch b/contrib-ITA/Integrations/ita/ra_tls_ita/helpers/gramine-v1.5-ci-examples.patch
index 429c5cb..99affdb 100644
--- a/contrib/Integrations/azure/ra_tls_maa/helpers/gramine-v1.5-ci-examples.patch
+++ b/contrib-ITA/Integrations/ita/ra_tls_ita/helpers/gramine-v1.5-ci-examples.patch
@@ -1,13 +1,13 @@
 diff --git a/CI-Examples/ra-tls-mbedtls/Makefile b/CI-Examples/ra-tls-mbedtls/Makefile
-index 4adc0eee275edc4508cd06eea5d818ec503f5200..6b42d6e7c6bf9973f26062f5973b032b822b0f5b 100644
+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: maa
-+maa: client_maa.manifest.sgx client_maa.sig
++.PHONY: ita
++ita: client_ita.manifest.sgx client_ita.sig
 +
  ############################# SSL DATA DEPENDENCY #############################
  
@@ -16,19 +16,19 @@ index 4adc0eee275edc4508cd06eea5d818ec503f5200..6b42d6e7c6bf9973f26062f5973b032b
  		--manifest $< \
  		--output $<.sgx
  
-+########################### CLIENT (MAA) MANIFEST #############################
++########################### CLIENT (ita) MANIFEST #############################
 +
-+client_maa.manifest: client.manifest.template
++client_ita.manifest: client.manifest.template
 +	gramine-manifest \
 +		-Dlog_level=$(GRAMINE_LOG_LEVEL) \
 +		-Darch_libdir=$(ARCH_LIBDIR) \
 +		$< >$@
 +
-+client_maa.manifest.sgx client_maa.sig: sgx_sign_client_maa
++client_ita.manifest.sgx client_ita.sig: sgx_sign_client_ita
 +	@:
 +
-+.INTERMEDIATE: sgx_sign_client_maa
-+sgx_sign_client_maa: client_maa.manifest client
++.INTERMEDIATE: sgx_sign_client_ita
++sgx_sign_client_ita: client_ita.manifest client
 +	gramine-sgx-sign \
 +		--manifest $< \
 +		--output $<.sgx
@@ -40,12 +40,12 @@ index 4adc0eee275edc4508cd06eea5d818ec503f5200..6b42d6e7c6bf9973f26062f5973b032b
  	./client dcap && exit 1 || echo "[ Success 1/1 ]"; \
  	kill -9 $$SERVER_ID
  
-+.PHONY: check_maa
-+check_maa: app maa
++.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 maa > OUTPUT; \
-+	./client maa 0 0 0 0 >> OUTPUT; \
++	./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 ]"
@@ -53,18 +53,18 @@ index 4adc0eee275edc4508cd06eea5d818ec503f5200..6b42d6e7c6bf9973f26062f5973b032b
 +	@(exit `grep -c "failed" "OUTPUT"`) && echo "[ Success 4/4 ]"
 +	@rm OUTPUT
 +
-+.PHONY: check_maa_fail
-+check_maa_fail: app maa
++.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 maa && exit 1 || echo "[ Success 1/1 ]"; \
++	./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 6b7d05609f6135488ba51bc317f49d3ea30855a3..ad51f1709b9a629012f1180969b57a7a7ca04dfe 100644
+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) {
@@ -75,8 +75,8 @@ index 6b7d05609f6135488ba51bc317f49d3ea30855a3..ad51f1709b9a629012f1180969b57a7a
 -            (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], "maa"))) {
-+        mbedtls_printf("USAGE: %s native|epid|dcap|maa [SGX measurements]\n", argv[0]);
++                strcmp(argv[1], "dcap") && strcmp(argv[1], "ita"))) {
++        mbedtls_printf("USAGE: %s native|epid|dcap|ita [SGX measurements]\n", argv[0]);
          return 1;
      }
  
@@ -84,46 +84,46 @@ index 6b7d05609f6135488ba51bc317f49d3ea30855a3..ad51f1709b9a629012f1180969b57a7a
                  return 1;
              }
          }
-+    } else if (!strcmp(argv[1], "maa")) {
-+        ra_tls_verify_lib = dlopen("libra_tls_verify_maa.so", RTLD_LAZY);
++    } 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 MAA but cannot find lib\n");
++            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 cc4e300d316d0a7cf83a69e4ca62711c845539d8..a93d19078be6940ff09c5840f5553416ea777346 100644
+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_maa
++/secret_prov/server_ita
  /secret_prov_minimal/client
  /secret_prov_minimal/server_epid
  /secret_prov_minimal/server_dcap
-+/secret_prov_minimal/server_maa
++/secret_prov_minimal/server_ita
  /secret_prov_pf/client
  /secret_prov_pf/server_epid
  /secret_prov_pf/server_dcap
-+/secret_prov_pf/server_maa
++/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 27806514c822831f1416017e812244736d7e2c51..94c3ba7dfde6ceb7b7f37360ab7c66def06a8aae 100644
+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: maa
-+maa: ssl/server.crt secret_prov_minimal/server_maa secret_prov/server_maa secret_prov_pf/server_maa \
++.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 #############################
@@ -133,8 +133,8 @@ index 27806514c822831f1416017e812244736d7e2c51..94c3ba7dfde6ceb7b7f37360ab7c66de
  %/server_dcap: %/server.c
  	$(CC) $< $(CFLAGS) $(LDFLAGS) -Wl,--no-as-needed -lsgx_urts -lsecret_prov_verify_dcap -pthread -o $@
  
-+%/server_maa: %/server.c
-+	$(CC) $< $(CFLAGS) $(LDFLAGS) -lsecret_prov_verify_maa -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 $@
@@ -143,11 +143,11 @@ index 27806514c822831f1416017e812244736d7e2c51..94c3ba7dfde6ceb7b7f37360ab7c66de
  
  	@rm OUTPUT
  
-+.PHONY: check_maa
-+check_maa: app maa
++.PHONY: check_ita
++check_ita: app ita
 +	# secret_prov_minimal
 +	cd secret_prov_minimal; \
-+	./server_maa >/dev/null & SERVER_ID=$$!; \
++	./server_ita >/dev/null & SERVER_ID=$$!; \
 +	../../../scripts/wait_for_server 60 127.0.0.1 4433; \
 +	gramine-sgx client > ../OUTPUT; \
 +	kill -9 $$SERVER_ID;
@@ -155,7 +155,7 @@ index 27806514c822831f1416017e812244736d7e2c51..94c3ba7dfde6ceb7b7f37360ab7c66de
 +
 +	# secret_prov
 +	cd secret_prov; \
-+	./server_maa >/dev/null & SERVER_ID=$$!; \
++	./server_ita >/dev/null & SERVER_ID=$$!; \
 +	../../../scripts/wait_for_server 60 127.0.0.1 4433; \
 +	gramine-sgx client > ../OUTPUT; \
 +	kill -9 $$SERVER_ID;
@@ -163,7 +163,7 @@ index 27806514c822831f1416017e812244736d7e2c51..94c3ba7dfde6ceb7b7f37360ab7c66de
 +
 +	# secret_prov_pf
 +	cd secret_prov_pf; \
-+	./server_maa wrap_key >/dev/null & SERVER_ID=$$!; \
++	./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;
diff --git a/contrib/Integrations/azure/ra_tls_maa/meson.build b/contrib-ITA/Integrations/ita/ra_tls_ita/meson.build
index 3838da1..25f7751 100644
--- a/contrib/Integrations/azure/ra_tls_maa/meson.build
+++ b/contrib-ITA/Integrations/ita/ra_tls_ita/meson.build
@@ -3,7 +3,7 @@
 #
 
 project(
-    'ra-tls-maa',
+    'ra-tls-ita',
     'c', 'cpp',
     version: '0.1',
     license: 'LGPLv3+',
@@ -51,7 +51,7 @@ threads_dep = dependency('threads')
 
 mbedtls_dep = dependency('mbedtls_gramine', static: true)
 
-# RA-TLS with MAA
+# RA-TLS with ITA
 
 ra_tls_map = meson.current_source_dir() / 'src' / 'ra_tls.map'
 ra_tls_link_args = [
@@ -65,8 +65,8 @@ ra_tls_includedir = ra_tls_dep.get_variable(pkgconfig: 'includedir') + '/gramine
 ra_tls_verify_lib = cc.find_library('ra_tls_verify', dirs: ra_tls_libdir)
 ra_tls_util_lib = cc.find_library('sgx_util', dirs: ra_tls_libdir)
 
-libra_tls_verify_maa = shared_library('ra_tls_verify_maa',
-    'src' / 'ra_tls_verify_maa.c',
+libra_tls_verify_ita = shared_library('ra_tls_verify_ita',
+    'src' / 'ra_tls_verify_ita.c',
 
     include_directories: ra_tls_includedir,
     link_args: ra_tls_link_args,
@@ -81,7 +81,7 @@ libra_tls_verify_maa = shared_library('ra_tls_verify_maa',
     install_rpath: get_option('prefix') / get_option('libdir'),
 )
 
-# Secret Prov with MAA
+# Secret Prov with ITA
 
 secret_prov_map = meson.current_source_dir() / 'src' / 'secret_prov.map'
 secret_prov_link_args = [
@@ -94,9 +94,9 @@ secret_prov_includedir = secret_prov_dep.get_variable(pkgconfig: 'includedir') +
 
 secret_prov_verify_lib = cc.find_library('secret_prov_verify', dirs: secret_prov_libdir)
 
-libsecret_prov_verify_maa = shared_library('secret_prov_verify_maa',
-    'src' / 'secret_prov_verify_maa.c',
-    'src' / 'ra_tls_verify_maa.c',
+libsecret_prov_verify_ita = shared_library('secret_prov_verify_ita',
+    'src' / 'secret_prov_verify_ita.c',
+    'src' / 'ra_tls_verify_ita.c',
 
     include_directories: secret_prov_includedir,
     link_args: secret_prov_link_args,
diff --git a/contrib/Integrations/azure/ra_tls_maa/src/ra_tls_verify_maa.c b/contrib-ITA/Integrations/ita/ra_tls_ita/src/ra_tls_verify_ita.c
similarity index 75%
rename from contrib/Integrations/azure/ra_tls_maa/src/ra_tls_verify_maa.c
rename to contrib-ITA/Integrations/ita/ra_tls_ita/src/ra_tls_verify_ita.c
index 9ff2557..d98ccf8 100644
--- a/contrib/Integrations/azure/ra_tls_maa/src/ra_tls_verify_maa.c
+++ b/contrib-ITA/Integrations/ita/ra_tls_ita/src/ra_tls_verify_ita.c
@@ -6,20 +6,20 @@
  *
  * This file contains the implementation of a verification callback for TLS libraries. The callback
  * verifies the correctness of a self-signed RA-TLS certificate with an SGX quote embedded in it.
- * The callback accesses a specific attestation provider of the Microsoft Azure Attestation (MAA)
- * for MAA-based attestation as part of the verification process. In particular, the callback sends
- * the Attestation request (JSON string that embeds the SGX quote + Enclave Held Data) to MAA via
+ * The callback accesses a specific attestation provider of the Intel Trust Authority (ITA)
+ * for ITA-based attestation as part of the verification process. In particular, the callback sends
+ * the Attestation request (JSON string that embeds the SGX quote + Enclave Held Data) to ITA via
  * HTTPS and receives an Attestation response (a JSON Web Token, or JWT, with claims). To ensure
  * authenticity of the Attestation response, the callback also obtains a set of JSON Web Keys, or
- * JWKs, from MAA and verifies the signature of JWT with the corresponding JWK's public key.
+ * JWKs, from ITA and verifies the signature of JWT with the corresponding JWK's public key.
  *
  * The HTTPS Attestation request is sent to the URL in the format:
- *     POST {instanceUrl}/attest/SgxEnclave?api-version=2022-08-01
+ *     POST {instanceUrl}/appraisal/{apiVersion}/attest
  *
  * The HTTPS "Get set of JWKs" request is sent to the URL in the format:
  *     GET {instanceUrl}/certs/
  *
- * {instanceUrl} is the attestation provider URL, e.g. `shareduks.uks.attest.azure.net`.
+ * {instanceUrl} is the attestation provider URL, e.g. `api.trustauthority.intel.com`.
  *
  * This file is part of the RA-TLS verification library which is typically linked into client
  * applications. This library is *not* thread-safe.
@@ -38,6 +38,7 @@
 
 #include <mbedtls/base64.h>
 #include <mbedtls/md.h>
+#include <mbedtls/rsa.h>
 #include <mbedtls/x509_crt.h>
 
 #include <cJSON.h>
@@ -54,36 +55,46 @@ extern verify_measurements_cb_t g_verify_measurements_cb;
         fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__); \
     } while (0)
 
-#define RA_TLS_MAA_PROVIDER_URL         "RA_TLS_MAA_PROVIDER_URL"
-#define RA_TLS_MAA_PROVIDER_API_VERSION "RA_TLS_MAA_PROVIDER_API_VERSION"
+#define WARN(fmt, ...)                                           \
+    do {                                                          \
+        fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__); \
+    } while (0)
+
+#define JWT_ISSUER_NAME                 "Intel Trust Authority"
+#define RA_TLS_ITA_PROVIDER_URL         "RA_TLS_ITA_PROVIDER_URL"
+#define RA_TLS_ITA_PORTAL_URL           "RA_TLS_ITA_PORTAL_URL"
+#define RA_TLS_ITA_API_KEY              "RA_TLS_ITA_API_KEY"
+#define RA_TLS_ITA_PROVIDER_API_VERSION "RA_TLS_ITA_PROVIDER_API_VERSION"
 
-#define MAA_URL_MAX_SIZE 256
+#define ITA_URL_MAX_SIZE 256
 
-/** MAA "Attest SGX Enclave" API endpoint. */
-#define MAA_URL_ATTEST_ENDPOINT "attest/SgxEnclave"
+/** ITA "Attest SGX Enclave" API endpoint. */
+#define ITA_URL_ATTEST_ENDPOINT "appraisal/%s/attest"
 
-/** MAA "Get Signing Certificates" API endpoint. */
-#define MAA_URL_CERTS_ENDPOINT "certs"
+/** ITA "Get Signing Certificates" API endpoint. */
+#define ITA_URL_CERTS_ENDPOINT "certs"
 
-/** Default API version for MAA API endpoints. */
-#define DEFAULT_MAA_PROVIDER_API_VERSION "2022-08-01"
+/** Default API version for ITA API endpoints. */
+#define DEFAULT_ITA_PROVIDER_API_VERSION "v1"
 
 /* Environment variables exposed by successful RA-TLS verification API */
-#define RA_TLS_MAA_JWT "RA_TLS_MAA_JWT"
-#define RA_TLS_MAA_SET_OF_JWKS "RA_TLS_MAA_SET_OF_JWKS"
+#define RA_TLS_ITA_JWT "RA_TLS_ita_JWT"
+#define RA_TLS_ITA_SET_OF_JWKS "RA_TLS_ita_SET_OF_JWKS"
 
-static char* g_maa_base_url = NULL;
-static char* g_maa_api_version = NULL;
+static char* g_ita_base_url = NULL;
+static char* g_ita_api_key = NULL;
+static char* g_ita_portal_url = NULL;
+static char* g_ita_api_version = NULL;
 
-/*! Context used in maa_*() calls */
-struct maa_context {
+/*! Context used in ita_*() calls */
+struct ita_context {
     bool curl_global_init_done;
     CURL* curl;                 /*!< CURL context for this session */
-    struct curl_slist* headers; /*!< Request headers sent to MAA attestation provider */
+    struct curl_slist* headers; /*!< Request headers sent to ITA attestation provider */
 };
 
-/*! MAA response (JWT token for `attest/` API, set of Signing keys for `certs/` API) */
-struct maa_response {
+/*! ITA response (JWT token for `attest/` API, set of Signing keys for `certs/` API) */
+struct ita_response {
     char* data;              /*!< response (JSON string) */
     size_t data_size;        /*!< size of \a data string */
 };
@@ -191,12 +202,12 @@ static int verify_quote_body_enclave_attributes(sgx_quote_body_t* quote_body,
 }
 
 /*!
- * \brief Parse response headers of the MAA attestation response (currently none).
+ * \brief Parse response headers of the ITA attestation response (currently none).
  *
  * \param[in] buffer   Single HTTP header.
  * \param[in] size     Together with \a count a size of \a buffer.
  * \param[in] count    Size of \a buffer, in \a size units.
- * \param[in] context  User data pointer (of type struct maa_response).
+ * \param[in] context  User data pointer (of type struct ita_response).
  *
  * \returns \a size * \a count
  *
@@ -216,7 +227,7 @@ static size_t header_callback(char* buffer, size_t size, size_t count, void* con
  * \param[in] buffer   Chunk containing HTTP body.
  * \param[in] size     Together with \a count a size of \a buffer.
  * \param[in] count    Size of \a buffer, in \a size units.
- * \param[in] context  User data pointer (of type struct maa_response).
+ * \param[in] context  User data pointer (of type struct ita_response).
  *
  * \returns \a size * \a count
  *
@@ -226,7 +237,7 @@ static size_t header_callback(char* buffer, size_t size, size_t count, void* con
 static size_t body_callback(char* buffer, size_t size, size_t count, void* context) {
     size_t total_size = size * count;
 
-    struct maa_response* response = context;
+    struct ita_response* response = context;
     assert(response);
 
     /* make space for the data, plus terminating \0 */
@@ -246,12 +257,12 @@ static size_t body_callback(char* buffer, size_t size, size_t count, void* conte
     return total_size;
 }
 
-static void response_cleanup(struct maa_response* response) {
+static void response_cleanup(struct ita_response* response) {
     free(response->data);
     free(response);
 }
 
-static void maa_cleanup(struct maa_context* context) {
+static void ita_cleanup(struct ita_context* context) {
     if (!context)
         return;
 
@@ -265,10 +276,13 @@ static void maa_cleanup(struct maa_context* context) {
     free(context);
 }
 
-static int maa_init(struct maa_context** out_context) {
-    int ret;
+static int ita_init(struct ita_context** out_context) {
+    int ret = -1;
+    const char* api_key_hdr_start = "x-api-key: ";
+    char* api_key_hdr = NULL;
+    size_t api_key_hdr_size;
 
-    struct maa_context* context = calloc(1, sizeof(*context));
+    struct ita_context* context = calloc(1, sizeof(*context));
     if (!context) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
@@ -288,6 +302,12 @@ static int maa_init(struct maa_context** out_context) {
         goto out;
     }
 
+    api_key_hdr_size = strlen(api_key_hdr_start) + strlen(g_ita_api_key) + 1;
+    api_key_hdr = malloc(api_key_hdr_size);
+    if (!api_key_hdr)
+        goto out;
+    snprintf(api_key_hdr, api_key_hdr_size, "%s%s", api_key_hdr_start, g_ita_api_key);
+
     curl_ret = curl_easy_setopt(context->curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
     if (curl_ret != CURLE_OK) {
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
@@ -300,6 +320,9 @@ static int maa_init(struct maa_context** out_context) {
         goto out;
     }
 
+    // set ITA API key in headers
+    context->headers = curl_slist_append(context->headers, api_key_hdr);
+    context->headers = curl_slist_append(context->headers, "Accept: application/json");
     context->headers = curl_slist_append(context->headers, "Content-Type: application/json");
     if (!context->headers) {
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
@@ -328,34 +351,34 @@ static int maa_init(struct maa_context** out_context) {
     ret = 0;
 out:
     if (ret < 0) {
-        maa_cleanup(context);
+        ita_cleanup(context);
     }
     return ret;
 }
 
-/*! Send GET request (empty) to MAA attestation provider's `certs/` API endpoint and save the
+/*! Send GET request (empty) to ITA attestation provider's `certs/` API endpoint and save the
  * resulting set of JWKs in \a out_set_of_jwks; caller is responsible for its cleanup */
-static int maa_get_signing_certs(struct maa_context* context, char** out_set_of_jwks) {
+static int ita_get_signing_certs(struct ita_context* context, char** out_set_of_jwks) {
     int ret;
 
     char* request_url = NULL;
-    struct maa_response* response = NULL;
+    struct ita_response* response = NULL;
 
-    /* prepare sending "GET certs" to MAA and receiving a response (using Curl) */
+    /* prepare sending "GET certs" to ITA and receiving a response (using Curl) */
     response = calloc(1, sizeof(*response));
     if (!response) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
     }
 
-    request_url = malloc(MAA_URL_MAX_SIZE);
+    request_url = malloc(ITA_URL_MAX_SIZE);
     if (!request_url) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
     }
 
-    ret = snprintf(request_url, MAA_URL_MAX_SIZE, "%s/%s/", g_maa_base_url, MAA_URL_CERTS_ENDPOINT);
-    if (ret < 0 || (size_t)ret >= MAA_URL_MAX_SIZE) {
+    ret = snprintf(request_url, ITA_URL_MAX_SIZE, "%s/%s", g_ita_portal_url, ITA_URL_CERTS_ENDPOINT);
+    if (ret < 0 || (size_t)ret >= ITA_URL_MAX_SIZE) {
         ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
         goto out;
     }
@@ -388,7 +411,7 @@ static int maa_get_signing_certs(struct maa_context* context, char** out_set_of_
     /* send the "GET certs" request, callbacks will store results in `response` */
     curl_ret = curl_easy_perform(context->curl);
     if (curl_ret != CURLE_OK) {
-        ERROR("Failed to send the MAA \"GET certs\" request to `%s`\n", request_url);
+        ERROR("Failed to send the ITA \"GET certs\" request to `%s`\n", request_url);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -401,14 +424,14 @@ static int maa_get_signing_certs(struct maa_context* context, char** out_set_of_
     }
 
     if (response_code != 200) {
-        ERROR("MAA \"GET certs\" request failed with code %ld and message `%s`\n", response_code,
+        ERROR("ITA \"GET certs\" request failed with code %ld and message `%s`\n", response_code,
               response->data);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
     if (!response->data) {
-        ERROR("MAA \"GET certs\" response doesn't have the set of JSON Web Keys (JWKs)\n");
+        ERROR("ITA \"GET certs\" response doesn't have the set of JSON Web Keys (JWKs)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -427,11 +450,11 @@ out:
     return ret;
 }
 
-/*! Send request (with \a quote embedded in it) to MAA attestation provider's `attest/` API endpoint
- * and save response in \a out_maa_response; caller is responsible for its cleanup */
-static int maa_send_request(struct maa_context* context, const void* quote, size_t quote_size,
+/*! Send request (with \a quote embedded in it) to ITA attestation provider's `attest/` API endpoint
+ * and save response in \a out_ita_response; caller is responsible for its cleanup */
+static int ita_send_request(struct ita_context* context, const void* quote, size_t quote_size,
                             const void* runtime_data, size_t runtime_data_size,
-                            struct maa_response** out_maa_response) {
+                            struct ita_response** out_ita_response) {
     int ret;
 
     char* quote_b64        = NULL;
@@ -439,7 +462,7 @@ static int maa_send_request(struct maa_context* context, const void* quote, size
     char* request_json     = NULL;
     char* request_url      = NULL;
 
-    struct maa_response* response = NULL;
+    struct ita_response* response = NULL;
 
     /* get needed base64url buffer size for quote, allocate it and encode the quote */
     size_t quote_b64_size = 0;
@@ -480,9 +503,8 @@ static int maa_send_request(struct maa_context* context, const void* quote, size
         goto out;
     }
 
-    /* construct JSON string with the attestation request to MAA */
-    const char* request_json_fmt = "{\"quote\": \"%s\", \"runtimeData\": "
-                                   "  {\"data\": \"%s\", \"dataType\": \"Binary\"}  }";
+    /* construct JSON string with the attestation request to ITA */
+    const char* request_json_fmt = "{\"quote\": \"%s\"}";
 
     size_t request_json_size = strlen(request_json_fmt) + 1 + quote_b64_size +
                                runtime_data_b64_size;
@@ -498,22 +520,22 @@ static int maa_send_request(struct maa_context* context, const void* quote, size
         goto out;
     }
 
-    /* prepare sending attestation request to MAA and receiving a response (using Curl) */
+    /* prepare sending attestation request to ITA and receiving a response (using Curl) */
     response = calloc(1, sizeof(*response));
     if (!response) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
     }
 
-    request_url = malloc(MAA_URL_MAX_SIZE);
+    request_url = malloc(ITA_URL_MAX_SIZE);
     if (!request_url) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
     }
 
-    ret = snprintf(request_url, MAA_URL_MAX_SIZE, "%s/" MAA_URL_ATTEST_ENDPOINT "?api-version=%s",
-                   g_maa_base_url, g_maa_api_version);
-    if (ret < 0 || (size_t)ret >= MAA_URL_MAX_SIZE) {
+    ret = snprintf(request_url, ITA_URL_MAX_SIZE, "%s/" ITA_URL_ATTEST_ENDPOINT "",
+                   g_ita_base_url, g_ita_api_version);
+    if (ret < 0 || (size_t)ret >= ITA_URL_MAX_SIZE) {
         ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
         goto out;
     }
@@ -552,7 +574,7 @@ static int maa_send_request(struct maa_context* context, const void* quote, size
     /* send the attestation request, callbacks will store results in `response` */
     curl_ret = curl_easy_perform(context->curl);
     if (curl_ret != CURLE_OK) {
-        ERROR("Failed to send the MAA Attestation request to `%s`\n", request_url);
+        ERROR("Failed to send the ITA Attestation request to `%s`\n", request_url);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -565,19 +587,19 @@ static int maa_send_request(struct maa_context* context, const void* quote, size
     }
 
     if (response_code != 200) {
-        ERROR("MAA Attestation request failed with code %ld and message `%s`\n", response_code,
+        ERROR("ITA Attestation request failed with code %ld and message `%s`\n", response_code,
               response->data);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
     if (!response->data) {
-        ERROR("MAA Attestation response doesn't have the JSON Web Token (JWT)\n");
+        ERROR("ITA Attestation response doesn't have the JSON Web Token (JWT)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
-    *out_maa_response = response;
+    *out_ita_response = response;
     ret = 0;
 
 out:
@@ -591,16 +613,16 @@ out:
     return ret;
 }
 
-/*! Verify the attestation response from MAA (the JWT token) and create a dummy SGX quote populated
+/*! Verify the attestation response from ITA (the JWT token) and create a dummy SGX quote populated
  * with the SGX-enclave measurements from this response in \a out_quote_body; caller is responsible
  * for its cleanup */
-static int maa_verify_response_output_quote(struct maa_response* response, const char* set_of_jwks,
+static int ita_verify_response_output_quote(struct ita_response* response, const char* set_of_jwks,
                                             sgx_quote_body_t** out_quote_body) {
     int ret;
 
     sgx_quote_body_t* quote_body = NULL;
 
-    char* maa_certs_url = NULL;
+    char* ita_certs_url = NULL;
 
     cJSON* json_response      = NULL;
     cJSON* json_token_header  = NULL;
@@ -626,14 +648,14 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
 
     json_response = cJSON_Parse(response->data);
     if (!json_response) {
-        ERROR("MAA Attestation response is not proper JSON\n");
+        ERROR("ITA Attestation response is not proper JSON\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
     cJSON* token_b64 = cJSON_GetObjectItem(json_response, "token");
     if (!cJSON_IsString(token_b64)) {
-        ERROR("MAA Attestation response doesn't contain the `token` string key (JWT)\n");
+        ERROR("ITA Attestation response doesn't contain the `token` string key (JWT)\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -643,7 +665,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     char* header_begin_in_token_b64 = token_b64->valuestring;
     char* header_end_in_token_b64   = strchr(header_begin_in_token_b64, '.');
     if (!header_end_in_token_b64) {
-        ERROR("MAA JWT is incorrectly formatted (cannot find the header)\n");
+        ERROR("ITA JWT is incorrectly formatted (cannot find the header)\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -659,7 +681,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     char* payload_begin_in_token_b64 = header_end_in_token_b64 + 1;
     char* payload_end_in_token_b64   = strchr(payload_begin_in_token_b64, '.');
     if (!payload_end_in_token_b64) {
-        ERROR("MAA JWT is incorrectly formatted (cannot find the payload)\n");
+        ERROR("ITA JWT is incorrectly formatted (cannot find the payload)\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -695,7 +717,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     ret = mbedtls_base64url_decode((uint8_t*)token_header, token_header_size, &token_header_size,
                                    (const uint8_t*)token_b64_header, strlen(token_b64_header));
     if (ret < 0) {
-        ERROR("MAA JWT is incorrectly formatted (the header is not Base64Url encoded)\n");
+        ERROR("ITA JWT is incorrectly formatted (the header is not Base64Url encoded)\n");
         goto out;
     }
 
@@ -715,7 +737,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     ret = mbedtls_base64url_decode((uint8_t*)token_payload, token_payload_size, &token_payload_size,
                                    (const uint8_t*)token_b64_payload, strlen(token_b64_payload));
     if (ret < 0) {
-        ERROR("MAA JWT is incorrectly formatted (the payload is not Base64Url encoded)\n");
+        ERROR("ITA JWT is incorrectly formatted (the payload is not Base64Url encoded)\n");
         goto out;
     }
 
@@ -737,7 +759,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
                                    &token_signature_size, (const uint8_t*)token_b64_signature,
                                    strlen(token_b64_signature));
     if (ret < 0) {
-        ERROR("MAA JWT is incorrectly formatted (the signature is not Base64Url encoded)\n");
+        ERROR("ITA JWT is incorrectly formatted (the signature is not Base64Url encoded)\n");
         goto out;
     }
 
@@ -745,7 +767,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
      * token_signature; the first two are JSON strings */
     json_token_header = cJSON_Parse(token_header);
     if (!json_token_header) {
-        ERROR("MAA JWT is incorrectly formatted (the header is not proper JSON)\n");
+        ERROR("ITA JWT is incorrectly formatted (the header is not proper JSON)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -755,40 +777,40 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     cJSON* token_header_typ = cJSON_GetObjectItem(json_token_header, "typ");
     cJSON* token_header_jku = cJSON_GetObjectItem(json_token_header, "jku");
 
-    /* currently only support JWTs with RSA-SHA256 signing */
-    if (!cJSON_IsString(token_header_alg) || strcmp(token_header_alg->valuestring, "RS256") ||
+    /* currently only support JWTs with PS384/RSASSA-PSS signing */
+    if (!cJSON_IsString(token_header_alg) || strcmp(token_header_alg->valuestring, "PS384") ||
             !cJSON_IsString(token_header_typ) || strcmp(token_header_typ->valuestring, "JWT") ||
             !cJSON_IsString(token_header_kid)) {
-        ERROR("MAA JWT header's `alg`, `typ` and/or `kid` fields contain unrecognized values\n");
+        ERROR("ITA JWT header's `alg`, `typ` and/or `kid` fields contain unrecognized values\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
 
     /* verify that we got the set of JWKs from the same endpoint as contained in `jku`; note that
      * `jku` field doesn't have the trailing slash */
-    maa_certs_url = malloc(MAA_URL_MAX_SIZE);
-    if (!maa_certs_url) {
+    ita_certs_url = malloc(ITA_URL_MAX_SIZE);
+    if (!ita_certs_url) {
         ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
         goto out;
     }
 
-    ret = snprintf(maa_certs_url, MAA_URL_MAX_SIZE, "%s/%s", g_maa_base_url,
-                   MAA_URL_CERTS_ENDPOINT);
-    if (ret < 0 || (size_t)ret >= MAA_URL_MAX_SIZE) {
+    ret = snprintf(ita_certs_url, ITA_URL_MAX_SIZE, "%s/%s", g_ita_portal_url,
+                   ITA_URL_CERTS_ENDPOINT);
+    if (ret < 0 || (size_t)ret >= ITA_URL_MAX_SIZE) {
         ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
         goto out;
     }
 
-    if (!cJSON_IsString(token_header_jku) || strcmp(token_header_jku->valuestring, maa_certs_url)) {
-        ERROR("MAA JWT header's `jku` field contains an unexpected URL (got `%s`, expected `%s`)\n",
-              token_header_jku->valuestring, maa_certs_url);
+    if (!cJSON_IsString(token_header_jku) || strcmp(token_header_jku->valuestring, ita_certs_url)) {
+        ERROR("ITA JWT header's `jku` field contains an unexpected URL (got `%s`, expected `%s`)\n",
+              token_header_jku->valuestring, ita_certs_url);
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
 
     json_token_payload = cJSON_Parse(token_payload);
     if (!json_token_payload) {
-        ERROR("MAA JWT is incorrectly formatted (the payload is not proper JSON)\n");
+        ERROR("ITA JWT is incorrectly formatted (the payload is not proper JSON)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -797,14 +819,14 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
      * the latter, find the corresponding array item and extract the X.509 cert from `x5c` field */
     json_jwks = cJSON_Parse(set_of_jwks);
     if (!json_jwks) {
-        ERROR("MAA set of JWKs is incorrectly formatted (the set is not proper JSON)\n");
+        ERROR("ITA set of JWKs is incorrectly formatted (the set is not proper JSON)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
     cJSON* keys_json_array = cJSON_GetObjectItem(json_jwks, "keys");
     if (!cJSON_IsArray(keys_json_array)) {
-        ERROR("MAA set of JWKs doesn't contain the `keys` JSON array\n");
+        ERROR("ITA set of JWKs doesn't contain the `keys` JSON array\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -819,14 +841,14 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
 
         /* currently only support RSA keys */
         if (!cJSON_IsString(key_kty) || strcmp(key_kty->valuestring, "RSA")) {
-            ERROR("MAA JWK's `kty` field contains an unexpected value (got `%s`, expected `%s`)\n",
+            ERROR("ITA JWK's `kty` field contains an unexpected value (got `%s`, expected `%s`)\n",
                   key_kty->valuestring, "RSA");
             ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
             goto out;
         }
 
         if (!cJSON_IsString(key_kid) || !cJSON_IsArray(key_x5c) || !cJSON_GetArraySize(key_x5c)) {
-            ERROR("MAA JWK's `kid` and/or `x5c` fields have incorrect types\n");
+            ERROR("ITA JWK's `kid` and/or `x5c` fields have incorrect types\n");
             ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
             goto out;
         }
@@ -835,7 +857,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
         if (!strcmp(key_kid->valuestring, token_header_kid->valuestring)) {
             cJSON* key_first_x509cert = cJSON_GetArrayItem(key_x5c, 0);
             if (!cJSON_IsString(key_first_x509cert)) {
-                ERROR("MAA JWK's `x5c` is not an array of string-value X.509 certificates\n");
+                ERROR("ITA JWK's `x5c` is not an array of string-value X.509 certificates\n");
                 ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
                 goto out;
             }
@@ -846,7 +868,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     }
 
     if (!token_signing_x509cert_b64) {
-        ERROR("Failed to find a corresponding JWK for the JWT received from MAA\n");
+        ERROR("Failed to find a corresponding JWK for the JWT received from ITA\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
@@ -871,77 +893,43 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
                                 (const uint8_t*)token_signing_x509cert_b64,
                                 strlen(token_signing_x509cert_b64));
     if (ret < 0) {
-        ERROR("MAA JWK's certificate is incorrectly formatted (not Base64 encoded)\n");
+        ERROR("ITA JWK's certificate is incorrectly formatted (not Base64 encoded)\n");
         goto out;
     }
 
     ret = mbedtls_x509_crt_parse(&token_signing_crt, (const uint8_t*)token_signing_x509cert,
                                  token_signing_x509cert_size);
     if (ret < 0) {
-        ERROR("MAA JWK's certificate is incorrectly formatted (not a proper X.509 cert)\n");
-        goto out;
-    }
-
-    /* perform signature verification of attestation token using the public key from the self-signed
-     * certificate obtained from `certs/` MAA API endpoint */
-    uint8_t md_sha256[32];
-    mbedtls_md_setup(&md_context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), /*hmac=*/0);
-    mbedtls_md_starts(&md_context);
-    mbedtls_md_update(&md_context, (const uint8_t*)token_b64_header, strlen(token_b64_header));
-    mbedtls_md_update(&md_context, (const uint8_t*)".", 1);
-    mbedtls_md_update(&md_context, (const uint8_t*)token_b64_payload,
-                      strlen(token_b64_payload));
-    mbedtls_md_finish(&md_context, md_sha256);
-
-    ret = mbedtls_pk_verify(&token_signing_crt.pk, MBEDTLS_MD_SHA256, md_sha256, sizeof(md_sha256),
-                            (const uint8_t*)token_signature, token_signature_size);
-    if (ret < 0) {
-        ERROR("Failed signature verification of JWT using the JWK's certificate\n");
+        ERROR("ITA JWK's certificate is incorrectly formatted (not a proper X.509 cert)\n");
         goto out;
     }
 
-    /*
-     * FIXME: the self-signed token-signing certificate obtained from the `certs/` MAA API endpoint
-     * (`token_signing_crt`) is supposed to embed an SGX quote; this SGX quote has the measurements
-     * like MRSIGNER that are published by the Azure Attestation team, and this SGX quote also has a
-     * binding to the public key of `token_signing_crt` via the classic hash-of-public-key:
-     *   token_signing_crt.sgx_quote.sgx_report.report_data = hash(token_signing_crt.pk)
-     *
-     * So ideally our code must extract the SGX quote from this certificate, verify this quote,
-     * verify that the quote binds to the cert's public key and verify the SGX measurements (against
-     * the ones published by the Azure Attestation team).
-     *
-     * Unfortunately, currently MAA has two problems: (a) not all MAA providers run inside the SGX
-     * environment, and (b) SGX measurements of MAA are not published online but must be requested
-     * from the MS Azure support team. Therefore, our code currently doesn't perform the
-     * SGX-specific verification of the token-signing certificate.
-     *
-     * For more info, read
-     * https://learn.microsoft.com/en-us/azure/attestation/overview#how-to-establish-trust-with-azure-attestation
-     */
-
     /* we verified the header and the signature of the received JWT, can trust its payload */
-    cJSON* x_ms_ver  = cJSON_GetObjectItem(json_token_payload, "x-ms-ver");
-    cJSON* x_ms_type = cJSON_GetObjectItem(json_token_payload, "x-ms-attestation-type");
+    cJSON *iss = cJSON_GetObjectItem(json_token_payload, "iss");
+    cJSON *ver = cJSON_GetObjectItem(json_token_payload, "ver");
 
     cJSON* expiration_time = cJSON_GetObjectItem(json_token_payload, "exp");
     cJSON* not_before_time = cJSON_GetObjectItem(json_token_payload, "nbf");
 
-    cJSON* sgx_is_debuggable = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-is-debuggable");
-    cJSON* sgx_mrenclave     = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-mrenclave");
-    cJSON* sgx_mrsigner      = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-mrsigner");
-    cJSON* sgx_product_id    = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-product-id");
-    cJSON* sgx_svn           = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-svn");
-    cJSON* sgx_report_data   = cJSON_GetObjectItem(json_token_payload, "x-ms-sgx-report-data");
-
-    /* XXX: we currently do not use/verify the following fields: x-ms-sgx-ehd, x-ms-sgx-config-id,
-     *      x-ms-sgx-config-svn, x-ms-sgx-isv-extended-product-id, x-ms-sgx-isv-family-id,
-     *      x-ms-sgx-collateral, x-ms-policy-hash */
-
-    if (!cJSON_IsString(x_ms_ver) || strcmp(x_ms_ver->valuestring, "1.0") ||
-            !cJSON_IsString(x_ms_type) || strcmp(x_ms_type->valuestring, "sgx")) {
-        ERROR("MAA JWT payload's `x-ms-ver` and/or `x-ms-attestation-type` fields contain "
-              "unrecognized values\n");
+    cJSON *attester_type = cJSON_GetObjectItem(json_token_payload, "attester_type");
+    cJSON *sgx_is_debuggable = cJSON_GetObjectItem(json_token_payload, "sgx_is_debuggable");
+    cJSON *sgx_mrenclave     = cJSON_GetObjectItem(json_token_payload, "sgx_mrenclave");
+    cJSON *sgx_mrsigner      = cJSON_GetObjectItem(json_token_payload, "sgx_mrsigner");
+    cJSON *sgx_product_id    = cJSON_GetObjectItem(json_token_payload, "sgx_isvprodid");
+    cJSON *sgx_svn           = cJSON_GetObjectItem(json_token_payload, "sgx_isvsvn");
+    cJSON *sgx_report_data   = cJSON_GetObjectItem(json_token_payload, "sgx_report_data");
+    // cJSON *sgx_tcb_status = cJSON_GetObjectItem(json_token_payload, "attester_tcb_status"); 
+
+    if (!cJSON_IsString(iss) || strcmp(iss->valuestring, "Intel Trust Authority")) {
+        ERROR("The JWT isn't issued by ITA");
+        ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
+        goto out;
+    }
+
+    if (!cJSON_IsString(ver) || strcmp(ver->valuestring, "1.0.0") ||
+        !cJSON_IsString(attester_type) || strcmp(attester_type->valuestring, "SGX")) {
+        ERROR("Intel Trust Authority JWT payload's `ver` and/or `attester_type` fields "
+               "contain unrecognized values\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -950,30 +938,28 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
      * NumericDate value -- the number of seconds from 1970-01-01 UTC (Seconds Since the Epoch).
      * Verify against the current time, otherwise this JWT must not be accepted. */
     if (!cJSON_IsNumber(expiration_time) || !cJSON_IsNumber(not_before_time)) {
-        ERROR("MAA JWT payload's `exp` and/or `nbf` fields have incorrect types\n");
+        ERROR("ITA JWT payload's `exp` and/or `nbf` fields have incorrect types\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
     time_t curr_time = time(NULL);
     if (curr_time == (time_t)-1) {
-        ERROR("Failed to fetch current time (to compare against `exp` and `nbf` of MAA JWT)\n");
+        ERROR("Failed to fetch current time (to compare against `exp` and `nbf` of ITA JWT)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
     if (!((time_t)not_before_time->valueint <= curr_time
                 && curr_time <= (time_t)expiration_time->valueint)) {
-        ERROR("MAA JWT is expired (nbf=%d, exp=%d in 'Seconds Since the Epoch' format)\n",
+        WARN("ITA JWT is expired (nbf=%d, exp=%d in 'Seconds Since the Epoch' format)\n",
               not_before_time->valueint, expiration_time->valueint);
-        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
-        goto out;
     }
 
     if (!cJSON_IsBool(sgx_is_debuggable) || !cJSON_IsString(sgx_mrenclave) ||
             !cJSON_IsString(sgx_mrsigner) || !cJSON_IsNumber(sgx_product_id) ||
             !cJSON_IsNumber(sgx_svn) || !cJSON_IsString(sgx_report_data)) {
-        ERROR("MAA JWT payload's `x-ms-sgx-is-debuggable`, `x-ms-sgx-mrenclave`, "
-              "`x-ms-sgx-mrsigner`, `x-ms-sgx-product-id`, `x-ms-sgx-svn` and/or "
-              "`x-ms-sgx-report-data` fields have incorrect types\n");
+        ERROR("ITA JWT payload's `sgx_is_debuggable`, `sgx_mrenclave`, "
+              "`sgx_mrsigner`, `sgx_isvprodid`, `sgx_isvsvn` and/or "
+              "`sgx_report_data` fields have incorrect types\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -995,7 +981,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     ret = parse_hex(sgx_mrenclave->valuestring, &quote_body->report_body.mr_enclave,
                     sizeof(quote_body->report_body.mr_enclave));
     if (ret < 0) {
-        ERROR("MAA JWT payload's `x-ms-sgx-mrenclave` field is not hex encoded\n");
+        ERROR("ITA JWT payload's `sgx_mrenclave` field is not hex encoded\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -1003,19 +989,19 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     ret = parse_hex(sgx_mrsigner->valuestring, &quote_body->report_body.mr_signer,
                     sizeof(quote_body->report_body.mr_signer));
     if (ret < 0) {
-        ERROR("MAA JWT payload's `x-ms-sgx-mrsigner` field is not hex encoded\n");
+        ERROR("ITA JWT payload's `sgx_mrsigner` field is not hex encoded\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
 
     static_assert(sizeof(quote_body->report_body.isv_prod_id) == 2); /* uint16_t */
     if (sgx_product_id->valueint == INT_MAX || sgx_product_id->valueint == INT_MIN) {
-        ERROR("MAA JWT payload's `x-ms-sgx-product-id` field is not an integer\n");
+        ERROR("ITA JWT payload's `sgx_isvprodid` field is not an integer\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
     if (sgx_product_id->valueint < 0 || sgx_product_id->valueint > USHRT_MAX) {
-        ERROR("MAA JWT payload's `x-ms-sgx-product-id` field is not uint16_t\n");
+        ERROR("ITA JWT payload's `sgx_isvprodid` field is not uint16_t\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -1023,12 +1009,12 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
 
     static_assert(sizeof(quote_body->report_body.isv_svn) == 2); /* uint16_t */
     if (sgx_svn->valueint == INT_MAX || sgx_svn->valueint == INT_MIN) {
-        ERROR("MAA JWT payload's `x-ms-sgx-svn` field is not an integer\n");
+        ERROR("ITA JWT payload's `sgx_isvsvn` field is not an integer\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
     if (sgx_svn->valueint < 0 || sgx_svn->valueint > USHRT_MAX) {
-        ERROR("MAA JWT payload's `x-ms-sgx-svn` field is not uint16_t\n");
+        ERROR("ITA JWT payload's `sgx_isvsvn` field is not uint16_t\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -1037,7 +1023,7 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
     ret = parse_hex(sgx_report_data->valuestring, &quote_body->report_body.report_data,
                     sizeof(quote_body->report_body.report_data));
     if (ret < 0) {
-        ERROR("MAA JWT payload's `x-ms-sgx-report-data` field is not hex encoded\n");
+        ERROR("ITA JWT payload's `sgx_report_data` field is not hex encoded\n");
         ret = MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
         goto out;
     }
@@ -1053,30 +1039,31 @@ static int maa_verify_response_output_quote(struct maa_response* response, const
      *
      * NOTE: manipulations with envvars are not thread-safe.
      */
-    if (getenv(RA_TLS_MAA_JWT)) {
-        ERROR("MAA JWT cannot be exposed through RA_TLS_MAA_JWT envvar because this envvar is "
+    if (getenv(RA_TLS_ITA_JWT)) {
+        ERROR("ITA JWT cannot be exposed through RA_TLS_ita_JWT envvar because this envvar is "
               "already used (you must unsetenv before calling RA-TLS verification)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
-    ret = setenv(RA_TLS_MAA_JWT, token_b64->valuestring, /*overwrite=*/1);
+    ret = setenv(RA_TLS_ITA_JWT, token_b64->valuestring, /*overwrite=*/1);
     if (ret < 0) {
-        ERROR("MAA JWT cannot be exposed through RA_TLS_MAA_JWT envvar because setenv() failed "
+        ERROR("ITA JWT cannot be exposed through RA_TLS_ita_JWT envvar because setenv() failed "
               "with error %d\n", errno);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
 
-    if (getenv(RA_TLS_MAA_SET_OF_JWKS)) {
-        ERROR("MAA \"Set of JWKs\" cannot be exposed through RA_TLS_MAA_SET_OF_JWKS envvar because "
+    if (getenv(RA_TLS_ITA_SET_OF_JWKS)) {
+        ERROR("ITA \"Set of JWKs\" cannot be exposed through RA_TLS_ita_SET_OF_JWKS envvar because "
               "this envvar is already used (you must unsetenv before calling RA-TLS "
               "verification)\n");
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
     }
-    ret = setenv(RA_TLS_MAA_SET_OF_JWKS, set_of_jwks, /*overwrite=*/1);
+    
+    ret = setenv(RA_TLS_ITA_SET_OF_JWKS, set_of_jwks, /*overwrite=*/1);
     if (ret < 0) {
-        ERROR("MAA \"Set of JWKs\" cannot be exposed through RA_TLS_MAA_SET_OF_JWKS envvar because "
+        ERROR("ITA \"Set of JWKs\" cannot be exposed through RA_TLS_ita_SET_OF_JWKS envvar because "
               "setenv() failed with error %d\n", errno);
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
         goto out;
@@ -1106,7 +1093,7 @@ out:
     free(token_payload);
     free(token_signature);
 
-    free(maa_certs_url);
+    free(ita_certs_url);
     free(token_signing_x509cert);
     mbedtls_x509_crt_free(&token_signing_crt);
     mbedtls_md_free(&md_context);
@@ -1131,14 +1118,14 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
 
     int ret;
 
-    struct maa_context* context   = NULL;
-    struct maa_response* response = NULL;
+    struct ita_context* context   = NULL;
+    struct ita_response* response = NULL;
     char* set_of_jwks             = NULL;
 
-    sgx_quote_body_t* quote_from_maa = NULL;
+    sgx_quote_body_t* quote_from_ita = NULL;
 
     if (results) {
-        /* TODO: when MAA becomes standard, add RA_TLS_ATTESTATION_SCHEME_MAA to core RA-TLS lib */
+        /* TODO: when ITA becomes standard, add RA_TLS_ATTESTATION_SCHEME_ita to core RA-TLS lib */
         results->attestation_scheme = RA_TLS_ATTESTATION_SCHEME_UNKNOWN;
         results->err_loc = AT_INIT;
     }
@@ -1155,16 +1142,28 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
         *flags = 0;
     }
 
-    ret = init_from_env(&g_maa_base_url, RA_TLS_MAA_PROVIDER_URL, /*default_val=*/NULL);
+    ret = init_from_env(&g_ita_base_url, RA_TLS_ITA_PROVIDER_URL, /*default_val=*/NULL);
+    if (ret < 0) {
+        ERROR("Failed to read the environment variable RA_TLS_ITA_PROVIDER_URL\n");
+        goto out;
+    }
+
+    ret = init_from_env(&g_ita_api_key, RA_TLS_ITA_API_KEY, /*default_val=*/NULL);
+    if (ret < 0) {
+        ERROR("Failed to read the environment variable RA_TLS_ITA_API_KEY\n");
+        goto out;
+    }
+
+    ret = init_from_env(&g_ita_portal_url, RA_TLS_ITA_PORTAL_URL, /*default_val=*/NULL);
     if (ret < 0) {
-        ERROR("Failed to read the environment variable RA_TLS_MAA_PROVIDER_URL\n");
+        ERROR("Failed to read the environment variable RA_TLS_ITA_PORTAL_URL\n");
         goto out;
     }
 
-    ret = init_from_env(&g_maa_api_version, RA_TLS_MAA_PROVIDER_API_VERSION,
-                        DEFAULT_MAA_PROVIDER_API_VERSION);
+    ret = init_from_env(&g_ita_api_version, RA_TLS_ITA_PROVIDER_API_VERSION,
+                        DEFAULT_ITA_PROVIDER_API_VERSION);
     if (ret < 0) {
-        ERROR("Failed to read the environment variable RA_TLS_MAA_PROVIDER_API_VERSION\n");
+        ERROR("Failed to read the environment variable RA_TLS_ITA_PROVIDER_API_VERSION\n");
         goto out;
     }
 
@@ -1190,7 +1189,7 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
         goto out;
 
     /* parse the public key of the received certificate into DER format -- it should be put into the
-     * Attestation request's `runtimeData` field (MAA will take a SHA256 hash over it and verify
+     * Attestation request's `runtimeData` field (ITA will take a SHA256 hash over it and verify
      * against the first 32 bytes of the SGX quote's report_data field) */
     uint8_t pk_der[PUB_KEY_SIZE_MAX] = {0};
     size_t pk_der_size;
@@ -1198,25 +1197,25 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
     if (ret < 0)
         goto out;
 
-    /* TODO: when MAA becomes standard, use results->maa.<fields> to expose more info on error */
+    /* TODO: when ITA becomes standard, use results->ita.<fields> to expose more info on error */
     if (results)
         results->err_loc = AT_VERIFY_EXTERNAL;
 
-    /* initialize the MAA context, get the set of JWKs from the `certs/` MAA API endpoint, send the
-     * SGX quote to the `attest/` MAA API endpoint, and finally receive and verify the attestation
+    /* initialize the ITA context, get the set of JWKs from the `certs/` ita API endpoint, send the
+     * SGX quote to the `attest/` ITA API endpoint, and finally receive and verify the attestation
      * response (JWT) */
-    ret = maa_init(&context);
+    ret = ita_init(&context);
     if (ret < 0) {
         goto out;
     }
 
     /* a set of JWKs may change over time, so we better get them every time */
-    ret = maa_get_signing_certs(context, &set_of_jwks);
+    ret = ita_get_signing_certs(context, &set_of_jwks);
     if (ret < 0) {
         goto out;
     }
 
-    ret = maa_send_request(context, quote, quote_size, pk_der, pk_der_size, &response);
+    ret = ita_send_request(context, quote, quote_size, pk_der, pk_der_size, &response);
     if (ret < 0 || !response || !response->data) {
         goto out;
     }
@@ -1224,19 +1223,19 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
     /* The attestation response is JWT -- we need to verify its signature using one of the set of
      * JWKs, as well as verify its header and payload, and construct an SGX quote from the
      * JWT-payload values to be used in further `verify_*` functions */
-    ret = maa_verify_response_output_quote(response, set_of_jwks, &quote_from_maa);
+    ret = ita_verify_response_output_quote(response, set_of_jwks, &quote_from_ita);
     if (ret < 0) {
         ret = MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
         goto out;
     }
 
-    /* verify that the SGX quote sent to MAA has the same measurements as the constructed from the
-     * MAA's JWT payload -- just for sanity */
+    /* verify that the SGX quote sent to ITA has the same measurements as the constructed from the
+     * ITA's JWT payload -- just for sanity */
     sgx_report_body_t* orig_body = &quote->body.report_body;
-    sgx_report_body_t* maa_body  = &quote_from_maa->report_body;
-    if (memcmp(&orig_body->report_data, &maa_body->report_data, sizeof(orig_body->report_data)) ||
-            memcmp(&orig_body->mr_enclave, &maa_body->mr_enclave, sizeof(orig_body->mr_enclave)) ||
-            memcmp(&orig_body->mr_signer, &maa_body->mr_signer, sizeof(orig_body->mr_signer))) {
+    sgx_report_body_t* ita_body  = &quote_from_ita->report_body;
+    if (memcmp(&orig_body->report_data, &ita_body->report_data, sizeof(orig_body->report_data)) ||
+            memcmp(&orig_body->mr_enclave, &ita_body->mr_enclave, sizeof(orig_body->mr_enclave)) ||
+            memcmp(&orig_body->mr_signer, &ita_body->mr_signer, sizeof(orig_body->mr_signer))) {
         ERROR("Failed verification of JWT's SGX measurements against the original SGX quote's "
               "measurements (for sanity)\n");
         ret = MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
@@ -1248,8 +1247,8 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
 
     /* verify enclave attributes from the SGX quote body, including the user-supplied verification
      * parameter "allow debug enclave"; NOTE: "allow outdated TCB", "allow HW config needed", "allow
-     * SW hardening needed" parameters are not used in MAA */
-    ret = verify_quote_body_enclave_attributes(quote_from_maa, getenv_allow_debug_enclave());
+     * SW hardening needed" parameters are not used in ITA */
+    ret = verify_quote_body_enclave_attributes(quote_from_ita, getenv_allow_debug_enclave());
     if (ret < 0) {
         ERROR("Failed verification of JWT's SGX enclave attributes\n");
         ret = MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
@@ -1262,13 +1261,13 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
     /* verify other relevant enclave information from the SGX quote */
     if (g_verify_measurements_cb) {
         /* use user-supplied callback to verify measurements */
-        ret = g_verify_measurements_cb((const char*)&quote_from_maa->report_body.mr_enclave,
-                                       (const char*)&quote_from_maa->report_body.mr_signer,
-                                       (const char*)&quote_from_maa->report_body.isv_prod_id,
-                                       (const char*)&quote_from_maa->report_body.isv_svn);
+        ret = g_verify_measurements_cb((const char*)&quote_from_ita->report_body.mr_enclave,
+                                       (const char*)&quote_from_ita->report_body.mr_signer,
+                                       (const char*)&quote_from_ita->report_body.isv_prod_id,
+                                       (const char*)&quote_from_ita->report_body.isv_svn);
     } else {
         /* use default logic to verify measurements */
-        ret = verify_quote_body_against_envvar_measurements(quote_from_maa);
+        ret = verify_quote_body_against_envvar_measurements(quote_from_ita);
     }
     if (ret < 0) {
         ERROR("Failed verification of JWT's SGX measurements\n");
@@ -1281,12 +1280,12 @@ int ra_tls_verify_callback(void* data, mbedtls_x509_crt* crt, int depth, uint32_
     ret = 0;
 out:
     if (context)
-        maa_cleanup(context);
+        ita_cleanup(context);
 
     if (response)
         response_cleanup(response);
 
     free(set_of_jwks);
-    free(quote_from_maa);
+    free(quote_from_ita);
     return ret;
 }
@dimakuv
Copy link
Author

dimakuv commented Jan 15, 2024

I am dumping my current notes and open questions in this comment.

Notes

Open questions

  • According to https://docs.trustauthority.intel.com/main/restapi/restapi-attestation.html, the only required field is the quote.

    • We already have runtime_data (this is sgx_report.user_data), so we can also use this ([Integrations/ita] Add RA-TLS/SecretProv libs for Intel Trust Authority #59 for some reason doesn't include it).
    • event_log and inittime_data seem to be TDX-specific? Look not useful for our SGX scenario.
    • verifier_nonce -- I think we can ignore it for now, the official docs say it is optional (and the nonce in SGX DCAP attestation is optional too; I think that's the same thing)
    • policy_ids -- this one I don't understand. PR [Integrations/ita] Add RA-TLS/SecretProv libs for Intel Trust Authority #59 doesn't specify any Policy ID in the POST request, and this field is marked as optional. But if we don't specify a policy, what does ITA do by default? Does it use the first policy, or it doesn't use any policy at all? If the latter, then this is insecure (we don't check the software identity at all, only the hardware identity). Must ask the ITA devs how policy_ids is supposed to work.
  • What is the https://portal.trustauthority.intel.com/certs endpoint? Can't find it in official documentation.

    • This endpoint is constructed via RA_TLS_ITA_PORTAL_URL (which is specified in the README as https://portal.trustauthority.intel.com) and the /certs endpoint.
    • This seems to mimic the logic of Microsoft's MAA (certificates with which the token is signed), but I don't see any mention of this endpoint in Intel ITA docs.
  • The part where our MAA code performs signature verification of JWT attestation token using the public key from the self-signed certificate obtained from certs/ API endpoint is completely missing in ITA (at least in [Integrations/ita] Add RA-TLS/SecretProv libs for Intel Trust Authority #59).

    • This means that connecting to https://portal.trustauthority.intel.com/certs endpoint and downloading the self-signed certificate is useless (see bullet item above).
    • Where do we get the public key with which to verify the JWT signature?
  • In MAA, the self-signed certificate obtained from certs/ API endpoint is supposed to contain the SGX quote, which reflects the well-known endourced-by-Microsoft SGX enclave measurements.

    • Since Intel ITA doesn't have such a self-signed certificate (?), how do we verify the authenticity of the ITA that generated the JWT token? Do we simply rely on Intel's https://api.trustauthority.intel.com website (to which we send our POST requests), or there's some additional cert/evidence that I missed in the docs?
  • In [Integrations/ita] Add RA-TLS/SecretProv libs for Intel Trust Authority #59, the expiration_time and not_before_time of the JWT token are considered warning-only (our MAA implementation fails if the JWT token dates are expired).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant