From 45d77795f6f9a55a3ff4f6f47d9c40ab490691ff Mon Sep 17 00:00:00 2001 From: Gunjan Munjal Date: Thu, 9 Sep 2021 15:21:16 -0700 Subject: [PATCH 1/8] Calling into thim agent to get collateral. --- src/Linux/curl_easy.h | 5 +- src/UnitTest/test_quote_prov.cpp | 14 ++- src/Windows/curl_easy.cpp | 9 +- src/Windows/curl_easy.h | 3 +- src/dcap_provider.cpp | 156 +++++++++++++++++++++++-------- src/dcap_provider.h | 12 +++ src/environment.h | 1 + 7 files changed, 151 insertions(+), 49 deletions(-) diff --git a/src/Linux/curl_easy.h b/src/Linux/curl_easy.h index d7f06e7d..fd18916b 100644 --- a/src/Linux/curl_easy.h +++ b/src/Linux/curl_easy.h @@ -36,7 +36,10 @@ class curl_easy char function[128]{}; }; - static std::unique_ptr create(const std::string& url, const std::string* const p_body); + static std::unique_ptr create( + const std::string& url, + const std::string* const p_body, + LPCWSTR httpVerb = L"GET"); ~curl_easy(); diff --git a/src/UnitTest/test_quote_prov.cpp b/src/UnitTest/test_quote_prov.cpp index affa50b7..d12653e5 100644 --- a/src/UnitTest/test_quote_prov.cpp +++ b/src/UnitTest/test_quote_prov.cpp @@ -458,7 +458,7 @@ static void GetCrlTest() { // This is the CRL DP used by Intel for leaf certs static const char* TEST_CRL_URL = - "https://api.trustedservices.intel.com/sgx/certification/v1/" + "https://api.trustedservices.intel.com/sgx/certification/v3/" "pckcrl?ca=processor"; sgx_ql_get_revocation_info_params_t params = { @@ -927,7 +927,11 @@ void SetupEnvironment(std::string version) #if defined __LINUX__ setenv( "AZDCAP_BASE_CERT_URL", - "https://global.acccache.azure.net/sgx/certificates", + "https://global.acccache.azure.net/sgx/certificates/", + 1); + setenv( + "AZDCAP_THIM_AGENT_URL", + "http://169.254.169.254/metadata/THIM/sgx/getCerts?", 1); setenv("AZDCAP_CLIENT_ID", "AzureDCAPTestsLinux", 1); if (!version.empty()) @@ -943,7 +947,10 @@ void SetupEnvironment(std::string version) } EXPECT_TRUE(SetEnvironmentVariableA( "AZDCAP_BASE_CERT_URL", - "https://global.acccache.azure.net/sgx/certificates")); + "https://global.acccache.azure.net/sgx/certificates/")); + EXPECT_TRUE(SetEnvironmentVariableA( + "AZDCAP_THIM_AGENT_URL", + "http://169.254.169.254/metadata/THIM/sgx/getCerts?")); EXPECT_TRUE( SetEnvironmentVariableA("AZDCAP_CLIENT_ID", "AzureDCAPTestsWindows")); #endif @@ -997,6 +1004,7 @@ TEST(testQuoteProv, quoteProviderTestsV2DataFromService) // Get the data from the service // SetupEnvironment("v2"); + ASSERT_TRUE(RunQuoteProviderTests()); ASSERT_TRUE(GetQveIdentityTest()); diff --git a/src/Windows/curl_easy.cpp b/src/Windows/curl_easy.cpp index 586078ca..9086b0d2 100644 --- a/src/Windows/curl_easy.cpp +++ b/src/Windows/curl_easy.cpp @@ -17,8 +17,8 @@ /////////////////////////////////////////////////////////////////////////////// // Constants /////////////////////////////////////////////////////////////////////////////// -static constexpr int maximum_retries = 5; -static constexpr int initial_retry_delay_ms = 20; +static constexpr int maximum_retries = 3; +static constexpr int initial_retry_delay_ms = 2000; static constexpr WCHAR content_type_header[] = L"Content-Type: application/json"; @@ -128,7 +128,8 @@ std::wstring UnicodeStringFromUtf8String(_In_ const std::string& ansiString) /////////////////////////////////////////////////////////////////////////////// std::unique_ptr curl_easy::create( const std::string& url, - const std::string* const p_body) + const std::string* const p_body, + LPCWSTR httpVerb) { struct make_unique_enabler : public curl_easy { @@ -191,7 +192,7 @@ std::unique_ptr curl_easy::create( curl->request.reset(WinHttpOpenRequest( curl->connectionHandle.get(), - L"GET", + httpVerb, urlToRetrieve.c_str(), nullptr, WINHTTP_NO_REFERER, diff --git a/src/Windows/curl_easy.h b/src/Windows/curl_easy.h index 0bfa0fe1..602275b3 100644 --- a/src/Windows/curl_easy.h +++ b/src/Windows/curl_easy.h @@ -39,7 +39,8 @@ class curl_easy }; static std::unique_ptr create( const std::string& url, - const std::string* const p_body); + const std::string* const p_body, + LPCWSTR httpVerb = L"GET"); ~curl_easy(); diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index b4dd91a3..925beb89 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -54,12 +54,15 @@ static const std::map default_values = { // New API version used to request PEM encoded CRLs constexpr char API_VERSION_LEGACY[] = "api-version=2018-10-01-preview"; constexpr char API_VERSION[] = "api-version=2020-02-12-preview"; - static char DEFAULT_CERT_URL[] = - "https://global.acccache.azure.net/sgx/certificates"; + "https://global.acccache.azure.net/sgx/certificates/"; static std::string cert_base_url = DEFAULT_CERT_URL; -static char DEFAULT_CLIENT_ID[] = "production_client"; +static char DEFAULT_THIM_AGENT_URL[] = + "http://169.254.169.254/metadata/THIM/sgx/getCerts?"; +static std::string thim_agent_base_url = DEFAULT_THIM_AGENT_URL; + +static char DEFAULT_CLIENT_ID[] = "Azure DCAP_client"; static std::string prod_client_id = DEFAULT_CLIENT_ID; static char DEFAULT_COLLATERAL_VERSION[] = "v3"; @@ -135,6 +138,25 @@ static std::string get_collateral_version() } } +static std::string get_agent_base_url() +{ + std::string env_base_url = get_env_variable(ENV_AZDCAP_THIM_AGENT_URL); + + if (env_base_url.empty()) + { + log(SGX_QL_LOG_WARNING, + "Using default THIM Agent base cert URL '%s'.", + thim_agent_base_url.c_str()); + return thim_agent_base_url; + } + + log(SGX_QL_LOG_INFO, + "Using %s envvar for base cert URL, set to '%s'.", + ENV_AZDCAP_THIM_AGENT_URL, + env_base_url.c_str()); + return env_base_url; +} + static std::string get_base_url() { std::string env_base_url = get_env_variable(ENV_AZDCAP_BASE_URL); @@ -456,10 +478,9 @@ void safe_cast(input_t in, output_t* out) *out = static_cast(in); } -// -// Build up the URL needed to fetch specific certificate information. -// -static std::string build_pck_cert_url(const sgx_ql_pck_cert_id_t& pck_cert_id) +static void build_pck_cert_url( + const sgx_ql_pck_cert_id_t& pck_cert_id, + collateral_fetch_url* collateral_url) { const std::string qe_id = format_as_hex_string(pck_cert_id.p_qe3_id, pck_cert_id.qe3_id_size); @@ -473,28 +494,34 @@ static std::string build_pck_cert_url(const sgx_ql_pck_cert_id_t& pck_cert_id) const std::string pce_id = format_as_big_endian_hex_string(pck_cert_id.pce_id); - std::string version = get_collateral_version(); - std::stringstream pck_cert_url; - pck_cert_url << get_base_url(); + + collateral_url->thim_service_url << get_base_url(); + collateral_url->thim_service_url << "noauth/pckcertificate?"; + collateral_url->thim_agent_url << get_agent_base_url(); + if (!version.empty()) { - pck_cert_url << '/'; - pck_cert_url << version; + collateral_url->thim_service_url << "version=" << version << '&'; + collateral_url->thim_agent_url << "TEEVersionType=" << version << '&'; } - pck_cert_url << '/' << qe_id; - pck_cert_url << '/' << cpu_svn; - pck_cert_url << '/' << pce_svn; - pck_cert_url << '/' << pce_id; - pck_cert_url << '?'; + collateral_url->thim_service_url << "qeid=" << qe_id << '&'; + collateral_url->thim_service_url << "cpusvn=" << cpu_svn << '&'; + collateral_url->thim_service_url << "pcesvn=" << pce_svn << '&'; + collateral_url->thim_service_url << "pceid=" << pce_id << '&'; + + collateral_url->thim_agent_url << "qeid=" << qe_id << '&'; + collateral_url->thim_agent_url << "cpusvn=" << cpu_svn << '&'; + collateral_url->thim_agent_url << "pcesvn=" << pce_svn << '&'; + collateral_url->thim_agent_url << "pceid=" << pce_id; std::string client_id = get_client_id(); + if (!client_id.empty()) { - pck_cert_url << "clientid=" << client_id << '&'; + collateral_url->thim_service_url << "clientid=" << client_id << '&'; } - pck_cert_url << API_VERSION_LEGACY; - return pck_cert_url.str(); + collateral_url->thim_service_url << API_VERSION_LEGACY; } // @@ -897,31 +924,80 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( try { - const std::string cert_url = build_pck_cert_url(*p_pck_cert_id); - if (auto cache_hit = try_cache_get(cert_url)) + collateral_fetch_url collateral_url; + build_pck_cert_url(*p_pck_cert_id, &collateral_url); + std::string cert_url = collateral_url.thim_service_url.str(); + std::string thim_agent_url = collateral_url.thim_agent_url.str(); + std::unique_ptr curl; + bool thim_agent_success = true; + + try { + curl = curl_easy::create(thim_agent_url, NULL); log(SGX_QL_LOG_INFO, - "Fetching quote config from cache: '%s'.", - cert_url.c_str()); + "Fetching quote config from THIM agent server: '%s'.", + thim_agent_url.c_str()); + curl->set_headers(headers::default_values); + curl->perform(); + } + catch (const std::bad_alloc&) + { + log_message(SGX_QL_LOG_ERROR, "Out of memory thrown"); + thim_agent_success = false; + return SGX_QL_ERROR_OUT_OF_MEMORY; + } + catch (const std::runtime_error& error) + { + log(SGX_QL_LOG_WARNING, + "Runtime exception thrown, error: %s", + error.what()); + thim_agent_success = false; + // Swallow adding file to cache. Library can + // operate without caching + // return SGX_QL_ERROR_UNEXPECTED; + } + catch (const std::exception& error) + { + log(SGX_QL_LOG_ERROR, + "Unknown exception thrown, error: %s", + error.what()); + thim_agent_success = false; + //return SGX_QL_ERROR_UNEXPECTED; + } + catch (const curl_easy::error& error) + { + log(SGX_QL_LOG_ERROR, + "error thrown, error code: %x: %s", + error.code, + error.what()); + thim_agent_success = false; + } + if (!thim_agent_success) { + if (auto cache_hit = try_cache_get(cert_url)) + { + log(SGX_QL_LOG_INFO, + "Fetching quote config from cache: '%s'.", + cert_url.c_str()); - *pp_quote_config = - (sgx_ql_config_t*)(new uint8_t[cache_hit->size()]); - memcpy(*pp_quote_config, cache_hit->data(), cache_hit->size()); + *pp_quote_config = + (sgx_ql_config_t*)(new uint8_t[cache_hit->size()]); + memcpy(*pp_quote_config, cache_hit->data(), cache_hit->size()); - // re-aligning the p_cert_data pointer - (*pp_quote_config)->p_cert_data = - (uint8_t*)(*pp_quote_config) + sizeof(sgx_ql_config_t); + // re-aligning the p_cert_data pointer + (*pp_quote_config)->p_cert_data = + (uint8_t*)(*pp_quote_config) + sizeof(sgx_ql_config_t); - return SGX_QL_SUCCESS; + return SGX_QL_SUCCESS; + } + + const std::string eppid_json = build_eppid_json(*p_pck_cert_id); + curl = curl_easy::create(cert_url, &eppid_json, L"POST"); + log(SGX_QL_LOG_INFO, + "Fetching quote config from remote server: '%s'.", + cert_url.c_str()); + curl->set_headers(headers::default_values); + curl->perform(); } - - const std::string eppid_json = build_eppid_json(*p_pck_cert_id); - const auto curl = curl_easy::create(cert_url, &eppid_json); - log(SGX_QL_LOG_INFO, - "Fetching quote config from remote server: '%s'.", - cert_url.c_str()); - curl->set_headers(headers::default_values); - curl->perform(); // we better get TCB info and the cert chain, else we cannot provide the // required data to the caller. @@ -977,7 +1053,7 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( *curl, headers::CACHE_CONTROL, &cache_control); auto retval = convert_to_intel_error(get_cache_header_operation); - if (retval == SGX_QL_SUCCESS) + if ((retval == SGX_QL_SUCCESS) and (!thim_agent_success)) { time_t expiry; if (get_cache_expiration_time(cache_control, cert_url, expiry)) diff --git a/src/dcap_provider.h b/src/dcap_provider.h index 9164d685..ac0238cc 100644 --- a/src/dcap_provider.h +++ b/src/dcap_provider.h @@ -6,6 +6,9 @@ #define PLATFORM_QUOTE_PROVIDER_H #include +#include + +using namespace std; /***************************************************************************** * Data types and interfaces for getting platform revocation info. This @@ -84,6 +87,15 @@ typedef sgx_plat_error_t (*sgx_get_qe_identity_info_t)( typedef void (*sgx_free_qe_identity_info_t)( sgx_qe_identity_info_t* p_qe_identity_info); +/***************************************************************************** + * Structure to pass THIM agent and THIM service URL + ****************************************************************************/ + +typedef struct _collateral_fetch_url { + std::stringstream thim_agent_url; // URL to fetch collateral from the agent + std::stringstream thim_service_url; // URL to fetch collateral from the service +} collateral_fetch_url; + /***************************************************************************** * Data types and interfaces for configuration the platform quote provider * library. diff --git a/src/environment.h b/src/environment.h index 57fa46e3..09f235ee 100644 --- a/src/environment.h +++ b/src/environment.h @@ -11,6 +11,7 @@ // modify or override these values as they can cause regressions in // caching service behavior. #define ENV_AZDCAP_BASE_URL "AZDCAP_BASE_CERT_URL" +#define ENV_AZDCAP_THIM_AGENT_URL "AZDCAP_THIM_AGENT_URL" #define ENV_AZDCAP_CLIENT_ID "AZDCAP_CLIENT_ID" #define ENV_AZDCAP_COLLATERAL_VER "AZDCAP_COLLATERAL_VERSION" #define ENV_AZDCAP_DEBUG_LOG "AZDCAP_DEBUG_LOG_LEVEL" From 0e3688b01982ff03173a52088cffc9920e7341d3 Mon Sep 17 00:00:00 2001 From: Gunjan Munjal Date: Thu, 9 Sep 2021 16:25:01 -0700 Subject: [PATCH 2/8] Updating linux curl request. --- src/Linux/curl_easy.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Linux/curl_easy.cpp b/src/Linux/curl_easy.cpp index 1a1909aa..30a7e82d 100644 --- a/src/Linux/curl_easy.cpp +++ b/src/Linux/curl_easy.cpp @@ -70,7 +70,7 @@ char const* curl_easy::error::what() const noexcept /////////////////////////////////////////////////////////////////////////////// // curl_easy implementation /////////////////////////////////////////////////////////////////////////////// -std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body) +std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body, LPCWSTR httpVerb)) { std::unique_ptr easy(new curl_easy); @@ -92,7 +92,12 @@ std::unique_ptr curl_easy::create(const std::string& url, const std:: if (p_body != nullptr && !p_body->empty()) { - easy->set_opt_or_throw(CURLOPT_CUSTOMREQUEST, "GET"); + if (httpVerb == L"POST") { + easy->set_opt_or_throw(CURLOPT_POST, 1L); + } + else { + easy->set_opt_or_throw(CURLOPT_HTTPGET, 1L); + } easy->set_opt_or_throw(CURLOPT_COPYPOSTFIELDS, p_body->c_str()); } From a8e56e8b2f2ecd782defab0cfda542f6d306b86f Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Tue, 19 Oct 2021 17:07:28 +0530 Subject: [PATCH 3/8] Sending cert fetch request to THIM agent using IMDS path. --- src/UnitTest/test_quote_prov.cpp | 4 +- src/Windows/curl_easy.cpp | 4 +- src/Windows/curl_easy.h | 1 + src/dcap_provider.cpp | 123 ++++++++++++++++++++----------- 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/src/UnitTest/test_quote_prov.cpp b/src/UnitTest/test_quote_prov.cpp index d12653e5..db0f6b0a 100644 --- a/src/UnitTest/test_quote_prov.cpp +++ b/src/UnitTest/test_quote_prov.cpp @@ -931,7 +931,7 @@ void SetupEnvironment(std::string version) 1); setenv( "AZDCAP_THIM_AGENT_URL", - "http://169.254.169.254/metadata/THIM/sgx/getCerts?", + "http://127.0.0.1:90/metadata/THIM/sgx/certificates?", 1); setenv("AZDCAP_CLIENT_ID", "AzureDCAPTestsLinux", 1); if (!version.empty()) @@ -950,7 +950,7 @@ void SetupEnvironment(std::string version) "https://global.acccache.azure.net/sgx/certificates/")); EXPECT_TRUE(SetEnvironmentVariableA( "AZDCAP_THIM_AGENT_URL", - "http://169.254.169.254/metadata/THIM/sgx/getCerts?")); + "http://127.0.0.1:90/metadata/THIM/sgx/certificates?")); EXPECT_TRUE( SetEnvironmentVariableA("AZDCAP_CLIENT_ID", "AzureDCAPTestsWindows")); #endif diff --git a/src/Windows/curl_easy.cpp b/src/Windows/curl_easy.cpp index 9086b0d2..cad4d5b5 100644 --- a/src/Windows/curl_easy.cpp +++ b/src/Windows/curl_easy.cpp @@ -129,6 +129,7 @@ std::wstring UnicodeStringFromUtf8String(_In_ const std::string& ansiString) std::unique_ptr curl_easy::create( const std::string& url, const std::string* const p_body, + DWORD dwFlags, LPCWSTR httpVerb) { struct make_unique_enabler : public curl_easy @@ -197,7 +198,7 @@ std::unique_ptr curl_easy::create( nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, - WINHTTP_FLAG_SECURE)); + dwFlags)); if (!curl->request) { @@ -420,6 +421,7 @@ void curl_easy::set_headers( } } + int8_t Int8FromHexAscii(char ch) { int8_t byteValue; diff --git a/src/Windows/curl_easy.h b/src/Windows/curl_easy.h index 602275b3..f62ef5d3 100644 --- a/src/Windows/curl_easy.h +++ b/src/Windows/curl_easy.h @@ -40,6 +40,7 @@ class curl_easy static std::unique_ptr create( const std::string& url, const std::string* const p_body, + DWORD dwFlags = WINHTTP_FLAG_SECURE, LPCWSTR httpVerb = L"GET"); ~curl_easy(); diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index 925beb89..7029c191 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -15,11 +15,11 @@ #include #include #include -#include #include +#include -#include "sgx_ql_lib_common.h" #include "environment.h" +#include "sgx_ql_lib_common.h" #ifdef __LINUX__ #include @@ -46,8 +46,10 @@ constexpr char REQUEST_ID[] = "Request-ID"; constexpr char CACHE_CONTROL[] = "Cache-Control"; static const std::map default_values = { - {"Content-Type", "application/json"} -}; + {"Content-Type", "application/json"}}; + +static const std::map thimagent_metadata = { + {"metadata", "true"}}; }; // namespace headers @@ -59,7 +61,7 @@ static char DEFAULT_CERT_URL[] = static std::string cert_base_url = DEFAULT_CERT_URL; static char DEFAULT_THIM_AGENT_URL[] = - "http://169.254.169.254/metadata/THIM/sgx/getCerts?"; + "http://169.254.169.254/metadata/THIM/sgx/certificates?"; static std::string thim_agent_base_url = DEFAULT_THIM_AGENT_URL; static char DEFAULT_CLIENT_ID[] = "Azure DCAP_client"; @@ -75,8 +77,8 @@ static char ROOT_CRL_NAME[] = static char PROCESSOR_CRL_NAME[] = "https%3a%2f%2fcertificates.trustedservices." "intel.com%2fintelsgxpckprocessor.crl"; static char PLATFORM_CRL_NAME[] = - "https%3a%2f%2fapi.trustedservices.intel.com%2fsgx%2fcertification%2fv3%2fpckcrl%3fca%3dplatform%26encoding%3dpem"; - + "https%3a%2f%2fapi.trustedservices.intel.com%2fsgx%2fcertification%2fv3%" + "2fpckcrl%3fca%3dplatform%26encoding%3dpem"; static const string CACHE_CONTROL_MAX_AGE = "max-age="; @@ -233,7 +235,10 @@ static inline quote3_error_t fill_qpl_string_buffer( // // Determine time cache should invalidate for given collateral // -bool get_cache_expiration_time(const string &cache_control, const string &url, time_t &expiration_time) +bool get_cache_expiration_time( + const string& cache_control, + const string& url, + time_t& expiration_time) { time_t max_age = 0; tm* max_age_s = localtime(&max_age); @@ -242,13 +247,15 @@ bool get_cache_expiration_time(const string &cache_control, const string &url, t constexpr int MAX_CACHE_TIME_SECONDS = 86400; if (index != string::npos) { - try + try { - cache_time_seconds = stoi(cache_control.substr(index + CACHE_CONTROL_MAX_AGE.length())); + cache_time_seconds = stoi( + cache_control.substr(index + CACHE_CONTROL_MAX_AGE.length())); if (cache_time_seconds > MAX_CACHE_TIME_SECONDS) { log(SGX_QL_LOG_ERROR, - "Caching control '%d' larger than maximum '%d' seconds. Collateral will not be cached", + "Caching control '%d' larger than maximum '%d' seconds. " + "Collateral will not be cached", cache_time_seconds, MAX_CACHE_TIME_SECONDS); return false; @@ -257,7 +264,8 @@ bool get_cache_expiration_time(const string &cache_control, const string &url, t catch (const std::invalid_argument& e) { log(SGX_QL_LOG_ERROR, - "Invalid argument thrown when parsing cache-control. Header text: '%s' Error: '%s'. Collateral will not be cached", + "Invalid argument thrown when parsing cache-control. Header " + "text: '%s' Error: '%s'. Collateral will not be cached", cache_control.c_str(), e.what()); return false; @@ -287,7 +295,7 @@ bool get_cache_expiration_time(const string &cache_control, const string &url, t // std::string get_collateral_friendly_name(CollateralTypes collateral_type) { - switch(collateral_type) + switch (collateral_type) { case CollateralTypes::TcbInfo: { @@ -503,17 +511,19 @@ static void build_pck_cert_url( if (!version.empty()) { collateral_url->thim_service_url << "version=" << version << '&'; - collateral_url->thim_agent_url << "TEEVersionType=" << version << '&'; + collateral_url->thim_agent_url << "version=" << version << '&'; } collateral_url->thim_service_url << "qeid=" << qe_id << '&'; collateral_url->thim_service_url << "cpusvn=" << cpu_svn << '&'; collateral_url->thim_service_url << "pcesvn=" << pce_svn << '&'; collateral_url->thim_service_url << "pceid=" << pce_id << '&'; - collateral_url->thim_agent_url << "qeid=" << qe_id << '&'; + collateral_url->thim_agent_url << "qeId=" << qe_id << '&'; collateral_url->thim_agent_url << "cpusvn=" << cpu_svn << '&'; collateral_url->thim_agent_url << "pcesvn=" << pce_svn << '&'; - collateral_url->thim_agent_url << "pceid=" << pce_id; + collateral_url->thim_agent_url << "pceid=" << pce_id << '&'; + + collateral_url->thim_agent_url << "cid=0" << '&'; std::string client_id = get_client_id(); @@ -522,6 +532,7 @@ static void build_pck_cert_url( collateral_url->thim_service_url << "clientid=" << client_id << '&'; } collateral_url->thim_service_url << API_VERSION_LEGACY; + collateral_url->thim_agent_url<< API_VERSION_LEGACY; } // @@ -785,7 +796,7 @@ static std::string build_enclave_id_url( static std::unique_ptr> try_cache_get( const std::string& cert_url) { - try + try { return local_cache_get(cert_url); } @@ -804,7 +815,7 @@ static std::string get_issuer_chain_cache_name(std::string url) static quote3_error_t get_collateral( CollateralTypes collateral_type, std::string url, - const char *issuer_chain_header, + const char* issuer_chain_header, std::vector& response_body, std::string& issuer_chain, const std::string* const request_body = nullptr) @@ -816,14 +827,17 @@ static quote3_error_t get_collateral( std::string issuer_chain_cache_name = get_issuer_chain_cache_name(url); if (auto cache_hit_collateral = try_cache_get(url)) { - if (auto cache_hit_issuer_chain = try_cache_get(issuer_chain_cache_name)) + if (auto cache_hit_issuer_chain = + try_cache_get(issuer_chain_cache_name)) { log(SGX_QL_LOG_INFO, "Fetching %s from cache: '%s'.", friendly_name.c_str(), url.c_str()); response_body = *cache_hit_collateral; - issuer_chain = std::string(cache_hit_issuer_chain->begin(), cache_hit_issuer_chain->end()); + issuer_chain = std::string( + cache_hit_issuer_chain->begin(), + cache_hit_issuer_chain->end()); return SGX_QL_SUCCESS; } } @@ -836,24 +850,33 @@ static quote3_error_t get_collateral( const auto curl_operation = curl_easy::create(url, request_body); curl_operation->perform(); response_body = curl_operation->get_body(); - auto get_issuer_chain_operation = - get_unescape_header(*curl_operation, issuer_chain_header, &issuer_chain); + auto get_issuer_chain_operation = get_unescape_header( + *curl_operation, issuer_chain_header, &issuer_chain); retval = convert_to_intel_error(get_issuer_chain_operation); if (retval == SGX_QL_SUCCESS) { std::string cache_control; - auto get_cache_header_operation = get_unescape_header(*curl_operation, headers::CACHE_CONTROL, &cache_control); + auto get_cache_header_operation = get_unescape_header( + *curl_operation, headers::CACHE_CONTROL, &cache_control); retval = convert_to_intel_error(get_cache_header_operation); if (retval == SGX_QL_SUCCESS) { - // Update the cache + // Update the cache time_t expiry = 0; if (get_cache_expiration_time(cache_control, url, expiry)) { - local_cache_add(url, expiry, response_body.size(), response_body.data()); - local_cache_add(issuer_chain_cache_name, expiry, issuer_chain.size(), issuer_chain.c_str()); + local_cache_add( + url, + expiry, + response_body.size(), + response_body.data()); + local_cache_add( + issuer_chain_cache_name, + expiry, + issuer_chain.size(), + issuer_chain.c_str()); } } } @@ -883,12 +906,15 @@ static quote3_error_t get_collateral( static std::string build_eppid_json(const sgx_ql_pck_cert_id_t& pck_cert_id) { - const std::string disable_ondemand = get_env_variable(ENV_AZDCAP_DISABLE_ONDEMAND); + const std::string disable_ondemand = + get_env_variable(ENV_AZDCAP_DISABLE_ONDEMAND); if (!disable_ondemand.empty()) { if (disable_ondemand == "1") { - log(SGX_QL_LOG_WARNING, "On demand registration disabled by environment variable. No eppid being sent to caching service"); + log(SGX_QL_LOG_WARNING, + "On demand registration disabled by environment variable. No " + "eppid being sent to caching service"); return ""; } } @@ -898,10 +924,11 @@ static std::string build_eppid_json(const sgx_ql_pck_cert_id_t& pck_cert_id) if (eppid.empty()) { - log(SGX_QL_LOG_WARNING, "No eppid provided - unable to send to caching service"); + log(SGX_QL_LOG_WARNING, + "No eppid provided - unable to send to caching service"); return ""; } - else + else { log(SGX_QL_LOG_INFO, "Sending the provided eppid to caching service"); } @@ -933,11 +960,11 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( try { - curl = curl_easy::create(thim_agent_url, NULL); + curl = curl_easy::create(thim_agent_url, NULL, 0); log(SGX_QL_LOG_INFO, "Fetching quote config from THIM agent server: '%s'.", thim_agent_url.c_str()); - curl->set_headers(headers::default_values); + curl->set_headers(headers::thimagent_metadata); curl->perform(); } catch (const std::bad_alloc&) @@ -962,7 +989,7 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( "Unknown exception thrown, error: %s", error.what()); thim_agent_success = false; - //return SGX_QL_ERROR_UNEXPECTED; + // return SGX_QL_ERROR_UNEXPECTED; } catch (const curl_easy::error& error) { @@ -972,7 +999,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( error.what()); thim_agent_success = false; } - if (!thim_agent_success) { + if (!thim_agent_success) + { if (auto cache_hit = try_cache_get(cert_url)) { log(SGX_QL_LOG_INFO, @@ -991,7 +1019,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( } const std::string eppid_json = build_eppid_json(*p_pck_cert_id); - curl = curl_easy::create(cert_url, &eppid_json, L"POST"); + curl = curl_easy::create( + cert_url, &eppid_json, WINHTTP_FLAG_SECURE, L"POST"); log(SGX_QL_LOG_INFO, "Fetching quote config from remote server: '%s'.", cert_url.c_str()); @@ -1049,12 +1078,12 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( // Get the cache control header std::string cache_control; - auto get_cache_header_operation = get_unescape_header( - *curl, headers::CACHE_CONTROL, &cache_control); + auto get_cache_header_operation = + get_unescape_header(*curl, headers::CACHE_CONTROL, &cache_control); auto retval = convert_to_intel_error(get_cache_header_operation); - if ((retval == SGX_QL_SUCCESS) and (!thim_agent_success)) - { + if ((retval == SGX_QL_SUCCESS) && (!thim_agent_success)) + { time_t expiry; if (get_cache_expiration_time(cache_control, cert_url, expiry)) { @@ -1540,7 +1569,7 @@ extern "C" quote3_error_t sgx_ql_get_quote_verification_collateral( if (strcmp(CRL_CA_PLATFORM, pck_ca) == 0) { - requested_ca = PLATFORM_CRL_NAME; + requested_ca = PLATFORM_CRL_NAME; root_crl_name = ROOT_CRL_NAME; } @@ -1568,9 +1597,9 @@ extern "C" quote3_error_t sgx_ql_get_quote_verification_collateral( std::string pck_crl_url = build_pck_crl_url(requested_ca, API_VERSION); operation_result = get_collateral( CollateralTypes::PckCrl, - pck_crl_url, - headers::CRL_ISSUER_CHAIN, - pck_crl, + pck_crl_url, + headers::CRL_ISSUER_CHAIN, + pck_crl, pck_issuer_chain); if (operation_result != SGX_QL_SUCCESS) { @@ -1618,7 +1647,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_verification_collateral( // Get QE Identity & Issuer Chain std::string issuer_chain_header; - std::string qe_identity_url = build_enclave_id_url(false, issuer_chain_header); + std::string qe_identity_url = + build_enclave_id_url(false, issuer_chain_header); const auto qe_identity_operation = curl_easy::create(qe_identity_url, nullptr); @@ -1766,7 +1796,10 @@ extern "C" quote3_error_t sgx_ql_get_qve_identity( quote3_error_t operation_result = get_collateral( CollateralTypes::QveIdentity, - qve_url, expected_issuer.c_str(), qve_identity, issuer_chain); + qve_url, + expected_issuer.c_str(), + qve_identity, + issuer_chain); if (operation_result != SGX_QL_SUCCESS) { log(SGX_QL_LOG_ERROR, From d7c727c3382917f3fbaddd7cb7b6d9144d9d5731 Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Wed, 27 Oct 2021 21:51:12 +0530 Subject: [PATCH 4/8] Resolving comments from last iteration. --- src/Linux/curl_easy.cpp | 3 +- src/Windows/UnitTests/packages.config | 11 ++-- .../dcap_provider_tests.vcxproj | 4 ++ .../dcap_provider_tests/packages.config | 1 + src/Windows/dll/dcap_provider.vcxproj | 5 ++ src/Windows/dll/packages.config | 5 +- src/dcap_provider.cpp | 51 ++++++++----------- 7 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/Linux/curl_easy.cpp b/src/Linux/curl_easy.cpp index 30a7e82d..0db10ab0 100644 --- a/src/Linux/curl_easy.cpp +++ b/src/Linux/curl_easy.cpp @@ -92,7 +92,8 @@ std::unique_ptr curl_easy::create(const std::string& url, const std:: if (p_body != nullptr && !p_body->empty()) { - if (httpVerb == L"POST") { + if (lstrcmpW(httpVerb, L"POST")) + { easy->set_opt_or_throw(CURLOPT_POST, 1L); } else { diff --git a/src/Windows/UnitTests/packages.config b/src/Windows/UnitTests/packages.config index 5c91377b..f00b14b7 100644 --- a/src/Windows/UnitTests/packages.config +++ b/src/Windows/UnitTests/packages.config @@ -1,6 +1,7 @@ - - - - - + + + + + + \ No newline at end of file diff --git a/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj b/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj index 0bd1b98d..3a406226 100644 --- a/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj +++ b/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj @@ -78,12 +78,16 @@ true + NativeRecommendedRules.ruleset + false true true + NativeRecommendedRules.ruleset + false true diff --git a/src/Windows/dcap_provider_tests/packages.config b/src/Windows/dcap_provider_tests/packages.config index 2e822b86..1b9d70b4 100644 --- a/src/Windows/dcap_provider_tests/packages.config +++ b/src/Windows/dcap_provider_tests/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/Windows/dll/dcap_provider.vcxproj b/src/Windows/dll/dcap_provider.vcxproj index 19645203..845bad64 100644 --- a/src/Windows/dll/dcap_provider.vcxproj +++ b/src/Windows/dll/dcap_provider.vcxproj @@ -35,9 +35,13 @@ true + NativeRecommendedRules.ruleset + false false + NativeRecommendedRules.ruleset + false @@ -60,6 +64,7 @@ Disabled _DEBUG;_LIB;%(PreprocessorDefinitions) true + true diff --git a/src/Windows/dll/packages.config b/src/Windows/dll/packages.config index e4bd4e9c..f00b14b7 100644 --- a/src/Windows/dll/packages.config +++ b/src/Windows/dll/packages.config @@ -1,6 +1,7 @@  - - + + + \ No newline at end of file diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index 7029c191..72d17d67 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -295,7 +295,7 @@ bool get_cache_expiration_time( // std::string get_collateral_friendly_name(CollateralTypes collateral_type) { - switch (collateral_type) + switch(collateral_type) { case CollateralTypes::TcbInfo: { @@ -488,7 +488,7 @@ void safe_cast(input_t in, output_t* out) static void build_pck_cert_url( const sgx_ql_pck_cert_id_t& pck_cert_id, - collateral_fetch_url* collateral_url) + collateral_fetch_url& collateral_url) { const std::string qe_id = format_as_hex_string(pck_cert_id.p_qe3_id, pck_cert_id.qe3_id_size); @@ -504,35 +504,35 @@ static void build_pck_cert_url( format_as_big_endian_hex_string(pck_cert_id.pce_id); std::string version = get_collateral_version(); - collateral_url->thim_service_url << get_base_url(); - collateral_url->thim_service_url << "noauth/pckcertificate?"; - collateral_url->thim_agent_url << get_agent_base_url(); + collateral_url.thim_service_url << get_base_url(); + collateral_url.thim_service_url << "noauth/pckcertificate?"; + collateral_url.thim_agent_url << get_agent_base_url(); if (!version.empty()) { - collateral_url->thim_service_url << "version=" << version << '&'; - collateral_url->thim_agent_url << "version=" << version << '&'; + collateral_url.thim_service_url << "version=" << version << '&'; + collateral_url.thim_agent_url << "version=" << version << '&'; } - collateral_url->thim_service_url << "qeid=" << qe_id << '&'; - collateral_url->thim_service_url << "cpusvn=" << cpu_svn << '&'; - collateral_url->thim_service_url << "pcesvn=" << pce_svn << '&'; - collateral_url->thim_service_url << "pceid=" << pce_id << '&'; + collateral_url.thim_service_url << "qeid=" << qe_id << '&'; + collateral_url.thim_service_url << "cpusvn=" << cpu_svn << '&'; + collateral_url.thim_service_url << "pcesvn=" << pce_svn << '&'; + collateral_url.thim_service_url << "pceid=" << pce_id << '&'; - collateral_url->thim_agent_url << "qeId=" << qe_id << '&'; - collateral_url->thim_agent_url << "cpusvn=" << cpu_svn << '&'; - collateral_url->thim_agent_url << "pcesvn=" << pce_svn << '&'; - collateral_url->thim_agent_url << "pceid=" << pce_id << '&'; + collateral_url.thim_agent_url << "qeId=" << qe_id << '&'; + collateral_url.thim_agent_url << "cpusvn=" << cpu_svn << '&'; + collateral_url.thim_agent_url << "pcesvn=" << pce_svn << '&'; + collateral_url.thim_agent_url << "pceid=" << pce_id << '&'; - collateral_url->thim_agent_url << "cid=0" << '&'; + collateral_url.thim_agent_url << "cid=0" << '&'; std::string client_id = get_client_id(); if (!client_id.empty()) { - collateral_url->thim_service_url << "clientid=" << client_id << '&'; + collateral_url.thim_service_url << "clientid=" << client_id << '&'; } - collateral_url->thim_service_url << API_VERSION_LEGACY; - collateral_url->thim_agent_url<< API_VERSION_LEGACY; + collateral_url.thim_service_url << API_VERSION_LEGACY; + collateral_url.thim_agent_url<< API_VERSION_LEGACY; } // @@ -952,11 +952,11 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( try { collateral_fetch_url collateral_url; - build_pck_cert_url(*p_pck_cert_id, &collateral_url); + build_pck_cert_url(*p_pck_cert_id, collateral_url); std::string cert_url = collateral_url.thim_service_url.str(); std::string thim_agent_url = collateral_url.thim_agent_url.str(); std::unique_ptr curl; - bool thim_agent_success = true; + bool thim_agent_success = false; try { @@ -966,11 +966,11 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( thim_agent_url.c_str()); curl->set_headers(headers::thimagent_metadata); curl->perform(); + thim_agent_success = true; } catch (const std::bad_alloc&) { log_message(SGX_QL_LOG_ERROR, "Out of memory thrown"); - thim_agent_success = false; return SGX_QL_ERROR_OUT_OF_MEMORY; } catch (const std::runtime_error& error) @@ -978,18 +978,12 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( log(SGX_QL_LOG_WARNING, "Runtime exception thrown, error: %s", error.what()); - thim_agent_success = false; - // Swallow adding file to cache. Library can - // operate without caching - // return SGX_QL_ERROR_UNEXPECTED; } catch (const std::exception& error) { log(SGX_QL_LOG_ERROR, "Unknown exception thrown, error: %s", error.what()); - thim_agent_success = false; - // return SGX_QL_ERROR_UNEXPECTED; } catch (const curl_easy::error& error) { @@ -997,7 +991,6 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( "error thrown, error code: %x: %s", error.code, error.what()); - thim_agent_success = false; } if (!thim_agent_success) { From dcc249b5e835cc0b47736336f8b544a1f0b092e4 Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Fri, 29 Oct 2021 17:05:11 +0530 Subject: [PATCH 5/8] Including a JSON parser to parse headers and certificate passed by THIM agent as a JSON response. --- src/UnitTest/test_quote_prov.cpp | 3 + src/Windows/UnitTests/UnitTests.vcxproj | 256 +++++++++--------- src/Windows/UnitTests/packages.config | 1 + .../dcap_provider_tests.vcxproj | 2 + .../dcap_provider_tests/packages.config | 1 + src/Windows/dll/dcap_provider.vcxproj | 3 + src/Windows/dll/packages.config | 1 + src/dcap_provider.cpp | 188 +++++++++---- src/environment.h | 1 + 9 files changed, 283 insertions(+), 173 deletions(-) diff --git a/src/UnitTest/test_quote_prov.cpp b/src/UnitTest/test_quote_prov.cpp index db0f6b0a..9c3be8ed 100644 --- a/src/UnitTest/test_quote_prov.cpp +++ b/src/UnitTest/test_quote_prov.cpp @@ -953,6 +953,9 @@ void SetupEnvironment(std::string version) "http://127.0.0.1:90/metadata/THIM/sgx/certificates?")); EXPECT_TRUE( SetEnvironmentVariableA("AZDCAP_CLIENT_ID", "AzureDCAPTestsWindows")); + EXPECT_TRUE( + SetEnvironmentVariableA("AZDCAP_CID", "cid=0")); + #endif } diff --git a/src/Windows/UnitTests/UnitTests.vcxproj b/src/Windows/UnitTests/UnitTests.vcxproj index 8790429f..e44bb601 100644 --- a/src/Windows/UnitTests/UnitTests.vcxproj +++ b/src/Windows/UnitTests/UnitTests.vcxproj @@ -1,128 +1,130 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {102d922a-e4d5-4b3f-9f83-bb001acefcbf} - Win32Proj - 10.0.17763.0 - Application - v141 - Unicode - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - NotUsing - pch.h - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - - - true - Console - - - - - NotUsing - pch.h - Disabled - X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - $(MSBuildThisFileDirectory)include;$(MSBuildProjectDirectory)\..\;$(MSBuildProjectDirectory)\..\ext\intel;$(SolutionDir)\ext\intel;$(MSBuildProjectDirectory)\..\..\;$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\include;%(AdditionalIncludeDirectories) - - - true - Console - $(MSBuildThisFileDirectory)..\\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.0\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Debug\gtest_main.lib;bcrypt.lib;%(AdditionalDependencies) - - - - - NotUsing - pch.h - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - true - Console - true - true - - - - - NotUsing - pch.h - X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - $(MSBuildThisFileDirectory)include;$(MSBuildProjectDirectory)\..\;$(MSBuildProjectDirectory)\..\ext\intel;$(SolutionDir)\ext\intel;$(MSBuildProjectDirectory)\..\..\;$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\include;%(AdditionalIncludeDirectories) - - - true - Console - true - true - $(MSBuildThisFileDirectory)..\\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.0\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Debug\gtest_main.lib;bcrypt.lib;%(AdditionalDependencies) - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {102d922a-e4d5-4b3f-9f83-bb001acefcbf} + Win32Proj + 10.0.17763.0 + Application + v141 + Unicode + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + NotUsing + pch.h + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + + + true + Console + + + + + NotUsing + pch.h + Disabled + X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + $(MSBuildThisFileDirectory)include;$(MSBuildProjectDirectory)\..\;$(MSBuildProjectDirectory)\..\ext\intel;$(SolutionDir)\ext\intel;$(MSBuildProjectDirectory)\..\..\;$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\include;%(AdditionalIncludeDirectories) + + + true + Console + $(MSBuildThisFileDirectory)..\\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.0\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Debug\gtest_main.lib;bcrypt.lib;%(AdditionalDependencies) + + + + + NotUsing + pch.h + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Console + true + true + + + + + NotUsing + pch.h + X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + $(MSBuildThisFileDirectory)include;$(MSBuildProjectDirectory)\..\;$(MSBuildProjectDirectory)\..\ext\intel;$(SolutionDir)\ext\intel;$(MSBuildProjectDirectory)\..\..\;$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\include;%(AdditionalIncludeDirectories) + + + true + Console + true + true + $(MSBuildThisFileDirectory)..\\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.0\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Debug\gtest_main.lib;bcrypt.lib;%(AdditionalDependencies) + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Windows/UnitTests/packages.config b/src/Windows/UnitTests/packages.config index f00b14b7..15123979 100644 --- a/src/Windows/UnitTests/packages.config +++ b/src/Windows/UnitTests/packages.config @@ -3,5 +3,6 @@ + \ No newline at end of file diff --git a/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj b/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj index 3a406226..6612b4d0 100644 --- a/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj +++ b/src/Windows/dcap_provider_tests/dcap_provider_tests.vcxproj @@ -185,12 +185,14 @@ + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + \ No newline at end of file diff --git a/src/Windows/dcap_provider_tests/packages.config b/src/Windows/dcap_provider_tests/packages.config index 1b9d70b4..d8907923 100644 --- a/src/Windows/dcap_provider_tests/packages.config +++ b/src/Windows/dcap_provider_tests/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file diff --git a/src/Windows/dll/dcap_provider.vcxproj b/src/Windows/dll/dcap_provider.vcxproj index 845bad64..fc620d4c 100644 --- a/src/Windows/dll/dcap_provider.vcxproj +++ b/src/Windows/dll/dcap_provider.vcxproj @@ -37,6 +37,7 @@ true NativeRecommendedRules.ruleset false + $(IncludePath) false @@ -123,6 +124,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + \ No newline at end of file diff --git a/src/Windows/dll/packages.config b/src/Windows/dll/packages.config index f00b14b7..15123979 100644 --- a/src/Windows/dll/packages.config +++ b/src/Windows/dll/packages.config @@ -3,5 +3,6 @@ + \ No newline at end of file diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index 72d17d67..b9a54aab 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include "environment.h" #include "sgx_ql_lib_common.h" + #ifdef __LINUX__ #include #else @@ -28,6 +30,7 @@ #include #endif +using nlohmann::json; using namespace std; // External function names are dictated by Intel @@ -70,6 +73,10 @@ static std::string prod_client_id = DEFAULT_CLIENT_ID; static char DEFAULT_COLLATERAL_VERSION[] = "v3"; static std::string default_collateral_version = DEFAULT_COLLATERAL_VERSION; +static char DEFAULT_CID[] = ""; +static std::string default_cid = DEFAULT_CID; + + static char CRL_CA_PROCESSOR[] = "processor"; static char CRL_CA_PLATFORM[] = "platform"; static char ROOT_CRL_NAME[] = @@ -159,6 +166,25 @@ static std::string get_agent_base_url() return env_base_url; } +static std::string get_cid() +{ + std::string env_base_url = get_env_variable(ENV_AZDCAP_CID); + + if (env_base_url.empty()) + { + log(SGX_QL_LOG_WARNING, + "Using default THIM Agent base cert URL '%s'.", + default_cid.c_str()); + return default_cid; + } + + log(SGX_QL_LOG_INFO, + "Using %s envvar for base cert URL, set to '%s'.", + ENV_AZDCAP_THIM_AGENT_URL, + env_base_url.c_str()); + return env_base_url; +} + static std::string get_base_url() { std::string env_base_url = get_env_variable(ENV_AZDCAP_BASE_URL); @@ -295,7 +321,7 @@ bool get_cache_expiration_time( // std::string get_collateral_friendly_name(CollateralTypes collateral_type) { - switch(collateral_type) + switch (collateral_type) { case CollateralTypes::TcbInfo: { @@ -328,6 +354,33 @@ std::string get_collateral_friendly_name(CollateralTypes collateral_type) } } +// +// extract raw value from response body, if exists +// +sgx_plat_error_t extract_from_json( + nlohmann::json json, + const std::string& header_item, + std::string* out_header) +{ + try + { + std::string raw_header = json[header_item].get(); + log(SGX_QL_LOG_INFO, + "raw_header %s:[%s]", + header_item.c_str(), + raw_header); + if (out_header != nullptr) + { + *out_header = raw_header; + } + } + catch (exception ex) + { + log(SGX_QL_LOG_ERROR, "Header '%s' is missing.", header_item.c_str()); + return SGX_PLAT_ERROR_UNEXPECTED_SERVER_RESPONSE; + } + return SGX_PLAT_ERROR_OK; +} // // get raw value for header_item item if exists // @@ -506,6 +559,7 @@ static void build_pck_cert_url( collateral_url.thim_service_url << get_base_url(); collateral_url.thim_service_url << "noauth/pckcertificate?"; + collateral_url.thim_agent_url << get_agent_base_url(); if (!version.empty()) @@ -523,24 +577,39 @@ static void build_pck_cert_url( collateral_url.thim_agent_url << "pcesvn=" << pce_svn << '&'; collateral_url.thim_agent_url << "pceid=" << pce_id << '&'; - collateral_url.thim_agent_url << "cid=0" << '&'; + std::string cid = get_cid(); + if (!cid.empty()) + { + collateral_url.thim_agent_url << "cid=0" << '&'; + } std::string client_id = get_client_id(); - if (!client_id.empty()) { collateral_url.thim_service_url << "clientid=" << client_id << '&'; } collateral_url.thim_service_url << API_VERSION_LEGACY; - collateral_url.thim_agent_url<< API_VERSION_LEGACY; + collateral_url.thim_agent_url << API_VERSION_LEGACY; } // // Build a complete cert chain from a completed curl object. // -static std::string build_cert_chain(const curl_easy& curl) +static std::string build_cert_chain(const curl_easy& curl, const nlohmann::json json) { - std::string leaf_cert(curl.get_body().begin(), curl.get_body().end()); + sgx_plat_error_t result = SGX_PLAT_ERROR_OK; + std::string leaf_cert; + std::string chain; + if (!json.empty()) + { + extract_from_json(json, "response", &leaf_cert); + extract_from_json(json, headers::PCK_CERT_ISSUER_CHAIN, &chain); + } + else + { + leaf_cert.assign(curl.get_body().begin(), curl.get_body().end()); + chain = curl.unescape(*curl.get_header(headers::PCK_CERT_ISSUER_CHAIN)); + } // The cache service does not return a newline in the response // response_body. Add one here so that we have a properly formatted chain. @@ -549,9 +618,6 @@ static std::string build_cert_chain(const curl_easy& curl) leaf_cert += "\n"; } - const std::string chain = - curl.unescape(*curl.get_header(headers::PCK_CERT_ISSUER_CHAIN)); - log(SGX_QL_LOG_INFO, "libquote_provider.so: [%s]", chain.c_str()); return leaf_cert + chain; } @@ -599,13 +665,22 @@ static sgx_plat_error_t hex_decode(const std::string& hex_string, T* decoded) // PCESVN(2 bytes)." // static sgx_plat_error_t parse_svn_values( + nlohmann::json json, const curl_easy& curl, sgx_ql_config_t* quote_config) { sgx_plat_error_t result = SGX_PLAT_ERROR_OK; std::string tcb; - result = get_raw_header(curl, headers::TCB_INFO, &tcb); + if (!json.empty()) + { + result = extract_from_json(json, headers::TCB_INFO, &tcb); + } + else + { + result = get_raw_header(curl, headers::TCB_INFO, &tcb); + } + if (result != SGX_PLAT_ERROR_OK) return result; @@ -952,11 +1027,15 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( try { collateral_fetch_url collateral_url; + std::vector response_body; + std::string temp; build_pck_cert_url(*p_pck_cert_id, collateral_url); std::string cert_url = collateral_url.thim_service_url.str(); std::string thim_agent_url = collateral_url.thim_agent_url.str(); std::unique_ptr curl; bool thim_agent_success = false; + sgx_ql_config_t temp_config{}; + nlohmann::json json_body; try { @@ -967,6 +1046,23 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( curl->set_headers(headers::thimagent_metadata); curl->perform(); thim_agent_success = true; + + // Parse the body returned by THIM agent to extract + // 1. Certificate + // 2. TCB Info + // 3. Cert Chain + // This will be returned to the caller. + response_body = curl->get_body(); + json_body = nlohmann::json::parse(response_body); + + if ((extract_from_json(json_body, headers::TCB_INFO, nullptr) != SGX_PLAT_ERROR_OK) || + (extract_from_json( + json_body, headers::PCK_CERT_ISSUER_CHAIN, nullptr) != + SGX_PLAT_ERROR_OK)) + { + log(SGX_QL_LOG_ERROR, "Required HTTP headers are missing."); + return SGX_QL_ERROR_UNEXPECTED; + } } catch (const std::bad_alloc&) { @@ -1019,28 +1115,28 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( cert_url.c_str()); curl->set_headers(headers::default_values); curl->perform(); - } - // we better get TCB info and the cert chain, else we cannot provide the - // required data to the caller. - if ((get_raw_header(*curl, headers::TCB_INFO, nullptr) != - SGX_PLAT_ERROR_OK) || - (get_raw_header(*curl, headers::PCK_CERT_ISSUER_CHAIN, nullptr) != - SGX_PLAT_ERROR_OK)) - { - log(SGX_QL_LOG_ERROR, "Required HTTP headers are missing."); - return SGX_QL_ERROR_UNEXPECTED; + // we better get TCB info and the cert chain, else we cannot + // provide the required data to the caller. + if ((get_raw_header(*curl, headers::TCB_INFO, nullptr) != + SGX_PLAT_ERROR_OK) || + (get_raw_header( + *curl, headers::PCK_CERT_ISSUER_CHAIN, nullptr) != + SGX_PLAT_ERROR_OK)) + { + log(SGX_QL_LOG_ERROR, "Required HTTP headers are missing."); + return SGX_QL_ERROR_UNEXPECTED; + } } - // parse the SVNs into a local data structure so we can handle any parse - // errors before allocating the output buffer - sgx_ql_config_t temp_config{}; - if (const sgx_plat_error_t err = parse_svn_values(*curl, &temp_config)) + // parse the SVNs into a local data structure so we can handle any + // parse errors before allocating the output buffer + if (const sgx_plat_error_t err = parse_svn_values(json_body, *curl, &temp_config)) { return convert_to_intel_error(err); } - const std::string cert_data = build_cert_chain(*curl); + const std::string cert_data = build_cert_chain(*curl, json_body); // copy the null-terminator for convenience (less error-prone) const uint32_t cert_data_size = @@ -1051,36 +1147,38 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( uint8_t* buf = new uint8_t[buf_size]; memset(buf, 0, buf_size); -#ifndef NDEBUG - const uint8_t* buf_end = buf + buf_size; -#endif + #ifndef NDEBUG + const uint8_t* buf_end = buf + buf_size; + #endif *pp_quote_config = reinterpret_cast(buf); buf += sizeof(sgx_ql_config_t); assert(buf <= buf_end); - (*pp_quote_config)->cert_cpu_svn = temp_config.cert_cpu_svn; (*pp_quote_config)->cert_pce_isv_svn = temp_config.cert_pce_isv_svn; (*pp_quote_config)->version = SGX_QL_CONFIG_VERSION_1; - (*pp_quote_config)->p_cert_data = buf; + (*pp_quote_config)->p_cert_data = buf; (*pp_quote_config)->cert_data_size = cert_data_size; memcpy( (*pp_quote_config)->p_cert_data, cert_data.data(), cert_data_size); buf += cert_data_size; assert(buf == buf_end); - // Get the cache control header - std::string cache_control; - auto get_cache_header_operation = - get_unescape_header(*curl, headers::CACHE_CONTROL, &cache_control); - - auto retval = convert_to_intel_error(get_cache_header_operation); - if ((retval == SGX_QL_SUCCESS) && (!thim_agent_success)) + if (!thim_agent_success) { - time_t expiry; - if (get_cache_expiration_time(cache_control, cert_url, expiry)) + // Get the cache control header + std::string cache_control; + auto get_cache_header_operation = + get_unescape_header(*curl, headers::CACHE_CONTROL, &cache_control); + + auto retval = convert_to_intel_error(get_cache_header_operation); + if ((retval == SGX_QL_SUCCESS) && (!thim_agent_success)) { - local_cache_add(cert_url, expiry, buf_size, *pp_quote_config); + time_t expiry; + if (get_cache_expiration_time(cache_control, cert_url, expiry)) + { + local_cache_add(cert_url, expiry, buf_size, *pp_quote_config); + } } } } @@ -1104,9 +1202,6 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( log(SGX_QL_LOG_WARNING, "Runtime exception thrown, error: %s", error.what()); - // Swallow adding file to cache. Library can - // operate without caching - // return SGX_QL_ERROR_UNEXPECTED; } catch (const std::exception& error) { @@ -1133,8 +1228,8 @@ extern "C" sgx_plat_error_t sgx_ql_get_revocation_info( { sgx_plat_error_t result = SGX_PLAT_ERROR_OK; - // Requests for higher versions work, but this function will ONLY return the - // highest version of output that it supports. + // Requests for higher versions work, but this function will ONLY return + // the highest version of output that it supports. if (params->version < SGX_QL_REVOCATION_INFO_VERSION_1) { log(SGX_QL_LOG_ERROR, @@ -1547,7 +1642,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_verification_collateral( if (*pp_quote_collateral != nullptr) { log(SGX_QL_LOG_ERROR, - "Collateral pointer is not null. This memory will be allocated " + "Collateral pointer is not null. This memory will be " + "allocated " "by " "this library"); return SGX_QL_ERROR_INVALID_PARAMETER; diff --git a/src/environment.h b/src/environment.h index 09f235ee..b92d8a7c 100644 --- a/src/environment.h +++ b/src/environment.h @@ -16,6 +16,7 @@ #define ENV_AZDCAP_COLLATERAL_VER "AZDCAP_COLLATERAL_VERSION" #define ENV_AZDCAP_DEBUG_LOG "AZDCAP_DEBUG_LOG_LEVEL" #define ENV_AZDCAP_DISABLE_ONDEMAND "AZDCAP_DISABLE_ONDEMAND" +#define ENV_AZDCAP_CID "AZDCAP_CID" #define MAX_ENV_VAR_LENGTH 2000 From 81fb0bc41f1b892c8ecf080c55519b49d1cedfe0 Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Fri, 29 Oct 2021 21:49:40 +0530 Subject: [PATCH 6/8] Updating function signatures to make linux compatible. --- src/Linux/curl_easy.cpp | 5 +- src/Linux/curl_easy.h | 3 +- src/UnitTest/test_quote_prov.cpp | 110 ++++++++++++++++++++----------- src/Windows/curl_easy.cpp | 6 +- src/Windows/curl_easy.h | 4 +- src/dcap_provider.cpp | 4 +- 6 files changed, 84 insertions(+), 48 deletions(-) diff --git a/src/Linux/curl_easy.cpp b/src/Linux/curl_easy.cpp index 0db10ab0..abf3302a 100644 --- a/src/Linux/curl_easy.cpp +++ b/src/Linux/curl_easy.cpp @@ -10,6 +10,7 @@ #include #include #include "private.h" +#include #ifdef __LINUX__ #include @@ -70,7 +71,7 @@ char const* curl_easy::error::what() const noexcept /////////////////////////////////////////////////////////////////////////////// // curl_easy implementation /////////////////////////////////////////////////////////////////////////////// -std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body, LPCWSTR httpVerb)) +std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body, unsigned long dwflag, std::wstring httpVerb)) { std::unique_ptr easy(new curl_easy); @@ -92,7 +93,7 @@ std::unique_ptr curl_easy::create(const std::string& url, const std:: if (p_body != nullptr && !p_body->empty()) { - if (lstrcmpW(httpVerb, L"POST")) + if (_wcsnicmp(httpVerb, L"POST")) { easy->set_opt_or_throw(CURLOPT_POST, 1L); } diff --git a/src/Linux/curl_easy.h b/src/Linux/curl_easy.h index fd18916b..5d4d485d 100644 --- a/src/Linux/curl_easy.h +++ b/src/Linux/curl_easy.h @@ -39,7 +39,8 @@ class curl_easy static std::unique_ptr create( const std::string& url, const std::string* const p_body, - LPCWSTR httpVerb = L"GET"); + unsigned long dwflags = 0x00800000, + std::wstringstd::wstring httpVerb = L"GET"); ~curl_easy(); diff --git a/src/UnitTest/test_quote_prov.cpp b/src/UnitTest/test_quote_prov.cpp index 9c3be8ed..ea92c844 100644 --- a/src/UnitTest/test_quote_prov.cpp +++ b/src/UnitTest/test_quote_prov.cpp @@ -101,44 +101,80 @@ static constexpr uint8_t TEST_FMSPC[] = {0x00, 0x90, 0x6E, 0xA1, 0x00, 0x00}; static constexpr uint8_t ICX_TEST_FMSPC[] = {0x00, 0x60, 0x6a, 0x00, 0x00, 0x00}; -// Test input (choose an arbitrary Azure server) -static uint8_t qe_id[16] = { - 0x00, - 0xfb, - 0xe6, - 0x73, - 0x33, - 0x36, - 0xea, - 0xf7, - 0xa4, - 0xe3, - 0xd8, - 0xb9, - 0x66, - 0xa8, - 0x2e, - 0x64}; - -static sgx_cpu_svn_t cpusvn = { - 0x04, - 0x04, - 0x02, - 0x04, - 0xff, - 0x80, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00}; + // Test input (choose an arbitrary Azure server) +// static uint8_t qe_id[16] = { +// 0x00, +// 0xfb, +// 0xe6, +// 0x73, +// 0x33, +// 0x36, +// 0xea, +// 0xf7, +// 0xa4, +// 0xe3, +// 0xd8, +// 0xb9, +// 0x66, +// 0xa8, +// 0x2e, +// 0x64}; + +static uint8_t qe_id[16] = {0x4e, + 0x77, + 0xbd, + 0x62, + 0xf4, + 0x64, + 0x0b, + 0xda, + 0x77, + 0xf6, + 0x77, + 0x97, + 0x60, + 0x9c, + 0xd8, + 0xed}; + +// static sgx_cpu_svn_t cpusvn = { +// 0x04, +// 0x04, +// 0x02, +// 0x04, +// 0xff, +// 0x80, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00, +// 0x00}; + +static sgx_cpu_svn_t cpusvn = {0x04, + 0x04, + 0x02, + 0x04, + 0x01, + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; +// static sgx_isv_svn_t pcesvn = 6; + +static sgx_isv_svn_t pcesvn = 5; -static sgx_isv_svn_t pcesvn = 6; static sgx_ql_pck_cert_id_t id = {qe_id, sizeof(qe_id), &cpusvn, &pcesvn, 0}; diff --git a/src/Windows/curl_easy.cpp b/src/Windows/curl_easy.cpp index cad4d5b5..c1741f83 100644 --- a/src/Windows/curl_easy.cpp +++ b/src/Windows/curl_easy.cpp @@ -129,8 +129,8 @@ std::wstring UnicodeStringFromUtf8String(_In_ const std::string& ansiString) std::unique_ptr curl_easy::create( const std::string& url, const std::string* const p_body, - DWORD dwFlags, - LPCWSTR httpVerb) + unsigned long dwFlags, + std::wstring httpVerb) { struct make_unique_enabler : public curl_easy { @@ -193,7 +193,7 @@ std::unique_ptr curl_easy::create( curl->request.reset(WinHttpOpenRequest( curl->connectionHandle.get(), - httpVerb, + httpVerb.c_str(), urlToRetrieve.c_str(), nullptr, WINHTTP_NO_REFERER, diff --git a/src/Windows/curl_easy.h b/src/Windows/curl_easy.h index f62ef5d3..1ca32b82 100644 --- a/src/Windows/curl_easy.h +++ b/src/Windows/curl_easy.h @@ -40,8 +40,8 @@ class curl_easy static std::unique_ptr create( const std::string& url, const std::string* const p_body, - DWORD dwFlags = WINHTTP_FLAG_SECURE, - LPCWSTR httpVerb = L"GET"); + unsigned long dwFlags = 0x00800000, + std::wstring httpVerb = L"GET"); ~curl_easy(); diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index b9a54aab..a219f4c7 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -597,7 +597,6 @@ static void build_pck_cert_url( // static std::string build_cert_chain(const curl_easy& curl, const nlohmann::json json) { - sgx_plat_error_t result = SGX_PLAT_ERROR_OK; std::string leaf_cert; std::string chain; if (!json.empty()) @@ -1108,8 +1107,7 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( } const std::string eppid_json = build_eppid_json(*p_pck_cert_id); - curl = curl_easy::create( - cert_url, &eppid_json, WINHTTP_FLAG_SECURE, L"POST"); + curl = curl_easy::create(cert_url, &eppid_json, 0x00800000, L"POST"); log(SGX_QL_LOG_INFO, "Fetching quote config from remote server: '%s'.", cert_url.c_str()); From 734a3e417df660eb9d7bfe28c0720256b8c907bc Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Tue, 2 Nov 2021 01:33:03 +0530 Subject: [PATCH 7/8] Updating linux side code. --- src/Linux/curl_easy.cpp | 54 ++++++++++++++++++++-------- src/Linux/curl_easy.h | 4 +-- src/UnitTest/test_quote_prov.cpp | 2 +- src/dcap_provider.cpp | 61 +++++++++++++++++++------------- 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/Linux/curl_easy.cpp b/src/Linux/curl_easy.cpp index abf3302a..4da2014a 100644 --- a/src/Linux/curl_easy.cpp +++ b/src/Linux/curl_easy.cpp @@ -15,12 +15,19 @@ #ifdef __LINUX__ #include #include +#include #else #include #include #include #endif +/////////////////////////////////////////////////////////////////////////////// +// Constants +/////////////////////////////////////////////////////////////////////////////// +static constexpr int maximum_retries = 3; +static constexpr int initial_retry_delay_ms = 2000; + /////////////////////////////////////////////////////////////////////////////// // Local Helper Functions /////////////////////////////////////////////////////////////////////////////// @@ -71,7 +78,7 @@ char const* curl_easy::error::what() const noexcept /////////////////////////////////////////////////////////////////////////////// // curl_easy implementation /////////////////////////////////////////////////////////////////////////////// -std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body, unsigned long dwflag, std::wstring httpVerb)) +std::unique_ptr curl_easy::create(const std::string& url, const std::string* const p_body, unsigned long dwflag, std::wstring httpVerb) { std::unique_ptr easy(new curl_easy); @@ -91,15 +98,17 @@ std::unique_ptr curl_easy::create(const std::string& url, const std:: easy->set_opt_or_throw(CURLOPT_FAILONERROR, 1L); easy->set_opt_or_throw(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + + if (wcscasecmp(httpVerb.c_str(), L"POST") == 0) + { + easy->set_opt_or_throw(CURLOPT_POST, 1L); + } + else + { + easy->set_opt_or_throw(CURLOPT_HTTPGET, 1L); + } if (p_body != nullptr && !p_body->empty()) { - if (_wcsnicmp(httpVerb, L"POST")) - { - easy->set_opt_or_throw(CURLOPT_POST, 1L); - } - else { - easy->set_opt_or_throw(CURLOPT_HTTPGET, 1L); - } easy->set_opt_or_throw(CURLOPT_COPYPOSTFIELDS, p_body->c_str()); } @@ -135,14 +144,29 @@ curl_easy::~curl_easy() void curl_easy::perform() const { - CURLcode result = curl_easy_perform(handle); - if (result == CURLE_HTTP_RETURNED_ERROR) + int retry_delay = initial_retry_delay_ms; + int attempts = 0; + long http_code = 0; + do { - long http_code = 0; - curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &http_code); - log(SGX_QL_LOG_ERROR, "HTTP error (%zd)", http_code); - } - throw_on_error(result, "curl_easy_perform"); + CURLcode result = curl_easy_perform(handle); + if ((result == CURLE_OPERATION_TIMEDOUT) && (attempts <= maximum_retries)) + { + attempts++; + curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &http_code); + log(SGX_QL_LOG_ERROR, "HTTP error (%zd)", http_code); + sleep(retry_delay); + retry_delay *= 2; + continue; + } + if (result == CURLE_HTTP_RETURNED_ERROR) + { + curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &http_code); + log(SGX_QL_LOG_ERROR, "HTTP error (%zd)", http_code); + } + throw_on_error(result, "curl_easy_perform"); + return; + }while(true); } const std::vector& curl_easy::get_body() const diff --git a/src/Linux/curl_easy.h b/src/Linux/curl_easy.h index 5d4d485d..2e48e076 100644 --- a/src/Linux/curl_easy.h +++ b/src/Linux/curl_easy.h @@ -39,8 +39,8 @@ class curl_easy static std::unique_ptr create( const std::string& url, const std::string* const p_body, - unsigned long dwflags = 0x00800000, - std::wstringstd::wstring httpVerb = L"GET"); + unsigned long dwFlags; + std::wstring httpVerb = L"GET"); ~curl_easy(); diff --git a/src/UnitTest/test_quote_prov.cpp b/src/UnitTest/test_quote_prov.cpp index ea92c844..c63133a1 100644 --- a/src/UnitTest/test_quote_prov.cpp +++ b/src/UnitTest/test_quote_prov.cpp @@ -967,7 +967,7 @@ void SetupEnvironment(std::string version) 1); setenv( "AZDCAP_THIM_AGENT_URL", - "http://127.0.0.1:90/metadata/THIM/sgx/certificates?", + "http://169.254.169.254/metadata/THIM/sgx/certificates?", 1); setenv("AZDCAP_CLIENT_ID", "AzureDCAPTestsLinux", 1); if (!version.empty()) diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index a219f4c7..e8e87ae6 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -22,7 +22,6 @@ #include "environment.h" #include "sgx_ql_lib_common.h" - #ifdef __LINUX__ #include #else @@ -30,7 +29,6 @@ #include #endif -using nlohmann::json; using namespace std; // External function names are dictated by Intel @@ -48,7 +46,7 @@ constexpr char ENCLAVE_ID_ISSUER_CHAIN[] = "SGX-Enclave-Identity-Issuer-Chain"; constexpr char REQUEST_ID[] = "Request-ID"; constexpr char CACHE_CONTROL[] = "Cache-Control"; -static const std::map default_values = { +static std::map default_values = { {"Content-Type", "application/json"}}; static const std::map thimagent_metadata = { @@ -76,7 +74,6 @@ static std::string default_collateral_version = DEFAULT_COLLATERAL_VERSION; static char DEFAULT_CID[] = ""; static std::string default_cid = DEFAULT_CID; - static char CRL_CA_PROCESSOR[] = "processor"; static char CRL_CA_PLATFORM[] = "platform"; static char ROOT_CRL_NAME[] = @@ -358,7 +355,7 @@ std::string get_collateral_friendly_name(CollateralTypes collateral_type) // extract raw value from response body, if exists // sgx_plat_error_t extract_from_json( - nlohmann::json json, + const nlohmann::json& json, const std::string& header_item, std::string* out_header) { @@ -374,7 +371,7 @@ sgx_plat_error_t extract_from_json( *out_header = raw_header; } } - catch (exception ex) + catch (const exception& ex) { log(SGX_QL_LOG_ERROR, "Header '%s' is missing.", header_item.c_str()); return SGX_PLAT_ERROR_UNEXPECTED_SERVER_RESPONSE; @@ -595,14 +592,18 @@ static void build_pck_cert_url( // // Build a complete cert chain from a completed curl object. // -static std::string build_cert_chain(const curl_easy& curl, const nlohmann::json json) +static std::string build_cert_chain( + const curl_easy& curl, + const nlohmann::json& json) { std::string leaf_cert; std::string chain; + std::string temp_chain; if (!json.empty()) { extract_from_json(json, "response", &leaf_cert); - extract_from_json(json, headers::PCK_CERT_ISSUER_CHAIN, &chain); + extract_from_json(json, headers::PCK_CERT_ISSUER_CHAIN, &temp_chain); + chain = curl.unescape(temp_chain); } else { @@ -664,7 +665,7 @@ static sgx_plat_error_t hex_decode(const std::string& hex_string, T* decoded) // PCESVN(2 bytes)." // static sgx_plat_error_t parse_svn_values( - nlohmann::json json, + const nlohmann::json& json, const curl_easy& curl, sgx_ql_config_t* quote_config) { @@ -1054,7 +1055,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( response_body = curl->get_body(); json_body = nlohmann::json::parse(response_body); - if ((extract_from_json(json_body, headers::TCB_INFO, nullptr) != SGX_PLAT_ERROR_OK) || + if ((extract_from_json(json_body, headers::TCB_INFO, nullptr) != + SGX_PLAT_ERROR_OK) || (extract_from_json( json_body, headers::PCK_CERT_ISSUER_CHAIN, nullptr) != SGX_PLAT_ERROR_OK)) @@ -1074,19 +1076,20 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( "Runtime exception thrown, error: %s", error.what()); } - catch (const std::exception& error) + catch (const curl_easy::error& error) { log(SGX_QL_LOG_ERROR, - "Unknown exception thrown, error: %s", + "error thrown, error code: %x: %s", + error.code, error.what()); } - catch (const curl_easy::error& error) + catch (const std::exception& error) { log(SGX_QL_LOG_ERROR, - "error thrown, error code: %x: %s", - error.code, + "Unknown exception thrown, error: %s", error.what()); } + if (!thim_agent_success) { if (auto cache_hit = try_cache_get(cert_url)) @@ -1107,7 +1110,13 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( } const std::string eppid_json = build_eppid_json(*p_pck_cert_id); - curl = curl_easy::create(cert_url, &eppid_json, 0x00800000, L"POST"); + if (eppid_json.empty()) + { + headers::default_values.insert( + std::pair("Content-Length", "0")); + } + curl = + curl_easy::create(cert_url, &eppid_json, 0x00800000, L"POST"); log(SGX_QL_LOG_INFO, "Fetching quote config from remote server: '%s'.", cert_url.c_str()); @@ -1129,7 +1138,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( // parse the SVNs into a local data structure so we can handle any // parse errors before allocating the output buffer - if (const sgx_plat_error_t err = parse_svn_values(json_body, *curl, &temp_config)) + if (const sgx_plat_error_t err = + parse_svn_values(json_body, *curl, &temp_config)) { return convert_to_intel_error(err); } @@ -1145,9 +1155,9 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( uint8_t* buf = new uint8_t[buf_size]; memset(buf, 0, buf_size); - #ifndef NDEBUG - const uint8_t* buf_end = buf + buf_size; - #endif +#ifndef NDEBUG + const uint8_t* buf_end = buf + buf_size; +#endif *pp_quote_config = reinterpret_cast(buf); buf += sizeof(sgx_ql_config_t); @@ -1155,7 +1165,7 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( (*pp_quote_config)->cert_cpu_svn = temp_config.cert_cpu_svn; (*pp_quote_config)->cert_pce_isv_svn = temp_config.cert_pce_isv_svn; (*pp_quote_config)->version = SGX_QL_CONFIG_VERSION_1; - (*pp_quote_config)->p_cert_data = buf; + (*pp_quote_config)->p_cert_data = buf; (*pp_quote_config)->cert_data_size = cert_data_size; memcpy( (*pp_quote_config)->p_cert_data, cert_data.data(), cert_data_size); @@ -1166,8 +1176,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( { // Get the cache control header std::string cache_control; - auto get_cache_header_operation = - get_unescape_header(*curl, headers::CACHE_CONTROL, &cache_control); + auto get_cache_header_operation = get_unescape_header( + *curl, headers::CACHE_CONTROL, &cache_control); auto retval = convert_to_intel_error(get_cache_header_operation); if ((retval == SGX_QL_SUCCESS) && (!thim_agent_success)) @@ -1175,7 +1185,8 @@ extern "C" quote3_error_t sgx_ql_get_quote_config( time_t expiry; if (get_cache_expiration_time(cache_control, cert_url, expiry)) { - local_cache_add(cert_url, expiry, buf_size, *pp_quote_config); + local_cache_add( + cert_url, expiry, buf_size, *pp_quote_config); } } } @@ -1995,4 +2006,4 @@ extern "C" quote3_error_t sgx_ql_get_root_ca_crl( error.what()); return SGX_QL_ERROR_UNEXPECTED; } -} +} \ No newline at end of file From 6e56c7bcd7f436f13d4ee5abcefec66d1201cb7f Mon Sep 17 00:00:00 2001 From: msft-gumunjal <81185076+msft-gumunjal@users.noreply.github.com> Date: Tue, 9 Nov 2021 16:16:57 +0530 Subject: [PATCH 8/8] Updating logging --- src/Linux/curl_easy.h | 2 +- src/dcap_provider.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Linux/curl_easy.h b/src/Linux/curl_easy.h index 2e48e076..aeccfc93 100644 --- a/src/Linux/curl_easy.h +++ b/src/Linux/curl_easy.h @@ -39,7 +39,7 @@ class curl_easy static std::unique_ptr create( const std::string& url, const std::string* const p_body, - unsigned long dwFlags; + unsigned long dwFlags = 0, std::wstring httpVerb = L"GET"); ~curl_easy(); diff --git a/src/dcap_provider.cpp b/src/dcap_provider.cpp index e8e87ae6..3bad6416 100644 --- a/src/dcap_provider.cpp +++ b/src/dcap_provider.cpp @@ -363,7 +363,7 @@ sgx_plat_error_t extract_from_json( { std::string raw_header = json[header_item].get(); log(SGX_QL_LOG_INFO, - "raw_header %s:[%s]", + "header from JSON %s:[%s]", header_item.c_str(), raw_header); if (out_header != nullptr)