From 46dda4f58f282fbd52b1c53ca85b5e38cd25131d Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 20 Feb 2023 16:58:20 +0000 Subject: [PATCH 01/25] WIP --- include/ccf/pal/attestation_sev_snp.h | 6 ++---- include/ccf/pal/attestation_sgx.h | 21 ++++++++++--------- include/ccf/service/code_digest.h | 8 ++++++- include/ccf/service/tables/code_id.h | 3 ++- include/ccf/service/tables/snp_measurements.h | 3 ++- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/ccf/pal/attestation_sev_snp.h b/include/ccf/pal/attestation_sev_snp.h index 5754244c3f2b..7d8163c12a08 100644 --- a/include/ccf/pal/attestation_sev_snp.h +++ b/include/ccf/pal/attestation_sev_snp.h @@ -15,12 +15,10 @@ namespace ccf::pal static constexpr size_t snp_attestation_report_data_size = 64; static constexpr size_t snp_attestation_measurement_size = 48; -#if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE) - using attestation_report_data = + using SnpAttestationReportData = std::array; - using attestation_measurement = + using SnpAttestationMeasurement = std::array; -#endif namespace snp { diff --git a/include/ccf/pal/attestation_sgx.h b/include/ccf/pal/attestation_sgx.h index 8b73da76d142..ad666a063445 100644 --- a/include/ccf/pal/attestation_sgx.h +++ b/include/ccf/pal/attestation_sgx.h @@ -2,23 +2,24 @@ // Licensed under the Apache 2.0 License. #pragma once -#if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include namespace ccf::pal { static constexpr size_t sgx_attestation_report_data_size = 32; static constexpr size_t sgx_attestation_measurement_size = 32; - using attestation_report_data = + using SgxAttestationReportData = std::array; - using attestation_measurement = + using SgxAttestationMeasurement = std::array; +#if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) + namespace sgx { // Set of wrappers for safe memory management @@ -80,5 +81,5 @@ namespace ccf::pal static constexpr oe_uuid_t oe_quote_format = {OE_FORMAT_UUID_SGX_ECDSA}; static constexpr auto report_data_claim_name = OE_CLAIM_SGX_REPORT_DATA; } -} -#endif \ No newline at end of file +#endif +} \ No newline at end of file diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index a692172d2e97..77d464314ccc 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -16,11 +16,17 @@ namespace ccf { struct CodeDigest { - pal::attestation_measurement data = {}; + // TODO: Enforce size invariants for SGX and SNP + std::vector data = {}; CodeDigest() = default; CodeDigest(const CodeDigest&) = default; + template + CodeDigest(const std::array& raw_measurement) : + data(raw_measurement.begin(), raw_meansurement.end()) + {} + CodeDigest& operator=(const CodeDigest&) = default; std::string hex_str() const diff --git a/include/ccf/service/tables/code_id.h b/include/ccf/service/tables/code_id.h index 1217554671e6..a0d3bd0b5177 100644 --- a/include/ccf/service/tables/code_id.h +++ b/include/ccf/service/tables/code_id.h @@ -2,12 +2,13 @@ // Licensed under the Apache 2.0 License. #pragma once +#include "ccf/pal/attestation_sgx.h" #include "ccf/service/code_digest.h" #include "ccf/service/map.h" namespace ccf { - using CodeIDs = ServiceMap; + using CodeIDs = ServiceMap; namespace Tables { diff --git a/include/ccf/service/tables/snp_measurements.h b/include/ccf/service/tables/snp_measurements.h index cff2da744e5b..5f81a633dc87 100644 --- a/include/ccf/service/tables/snp_measurements.h +++ b/include/ccf/service/tables/snp_measurements.h @@ -2,12 +2,13 @@ // Licensed under the Apache 2.0 License. #pragma once +#include "ccf/pal/attestation_sev_snp.h" #include "ccf/service/code_digest.h" #include "ccf/service/map.h" namespace ccf { - using SnpMeasurements = ServiceMap; + using SnpMeasurements = ServiceMap; namespace Tables { From 3cb4ca289073713c29db3bd342c0a96f710f1d34 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 21 Feb 2023 15:53:33 +0000 Subject: [PATCH 02/25] Just about builds --- include/ccf/pal/attestation.h | 22 ++- include/ccf/service/code_digest.h | 11 +- include/ccf/service/tables/code_id.h | 2 +- include/ccf/service/tables/snp_measurements.h | 3 +- src/endpoints/common_endpoint_registry.cpp | 12 +- src/node/node_state.h | 2 +- src/node/quote.cpp | 17 +- src/node/rpc/member_frontend.h | 170 +++++++++--------- src/service/genesis_gen.h | 17 +- 9 files changed, 147 insertions(+), 109 deletions(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index c640c3319fd6..9ec4cf138d2a 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -22,6 +22,10 @@ namespace ccf::pal { + // TODO: Change this + using AttestationReportData = SnpAttestationReportData; + using AttestationMeasurement = SnpAttestationMeasurement; + // Caller-supplied callback used to retrieve endorsements as specified by // the config argument. When called back, the quote_info argument will have // already been populated with the raw quote. @@ -33,8 +37,8 @@ namespace ccf::pal // SGX, this does not require external dependencies (Open Enclave for SGX). static void verify_snp_attestation_report( const QuoteInfo& quote_info, - attestation_measurement& unique_id, - attestation_report_data& report_data) + AttestationMeasurement& unique_id, + AttestationReportData& report_data) { if (quote_info.format != QuoteFormat::amd_sev_snp_v1) { @@ -202,7 +206,7 @@ namespace ccf::pal #if defined(PLATFORM_VIRTUAL) static void generate_quote( - attestation_report_data& report_data, + AttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -216,7 +220,7 @@ namespace ccf::pal #elif defined(PLATFORM_SNP) static void generate_quote( - attestation_report_data& report_data, + AttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -274,8 +278,8 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - attestation_measurement& unique_id, - attestation_report_data& report_data) + AttestationMeasurement& unique_id, + AttestationReportData& report_data) { auto is_sev_snp = access(snp::DEVICE, F_OK) == 0; @@ -317,7 +321,7 @@ namespace ccf::pal #else // SGX static void generate_quote( - attestation_report_data& report_data, + AttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -377,8 +381,8 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - attestation_measurement& unique_id, - attestation_report_data& report_data) + AttestationMeasurement& unique_id, + AttestationReportData& report_data) { if (quote_info.format == QuoteFormat::insecure_virtual) { diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 77d464314ccc..f4348209f4c9 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -5,6 +5,7 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" #include "ccf/ds/json.h" +#include "ccf/pal/attestation.h" #if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE) # include "ccf/pal/attestation_sev_snp.h" @@ -17,15 +18,15 @@ namespace ccf struct CodeDigest { // TODO: Enforce size invariants for SGX and SNP - std::vector data = {}; + pal::AttestationMeasurement data; CodeDigest() = default; CodeDigest(const CodeDigest&) = default; - template - CodeDigest(const std::array& raw_measurement) : - data(raw_measurement.begin(), raw_meansurement.end()) - {} + // template + // CodeDigest(const std::array& raw_measurement) : + // data(raw_measurement.begin(), raw_measurement.end()) + // {} CodeDigest& operator=(const CodeDigest&) = default; diff --git a/include/ccf/service/tables/code_id.h b/include/ccf/service/tables/code_id.h index a0d3bd0b5177..d1ab94c8bcb6 100644 --- a/include/ccf/service/tables/code_id.h +++ b/include/ccf/service/tables/code_id.h @@ -8,7 +8,7 @@ namespace ccf { - using CodeIDs = ServiceMap; + using CodeIDs = ServiceMap; namespace Tables { diff --git a/include/ccf/service/tables/snp_measurements.h b/include/ccf/service/tables/snp_measurements.h index 5f81a633dc87..45b4cbe4526c 100644 --- a/include/ccf/service/tables/snp_measurements.h +++ b/include/ccf/service/tables/snp_measurements.h @@ -8,7 +8,8 @@ namespace ccf { - using SnpMeasurements = ServiceMap; + using SnpMeasurements = + ServiceMap; namespace Tables { diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 73e962959cca..20d8c28a7635 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -251,8 +251,10 @@ namespace ccf auto codes_ids = ctx.tx.template ro(Tables::NODE_CODE_IDS); codes_ids->foreach( - [&out](const ccf::CodeDigest& cd, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(cd.data); + [&out]( + const ccf::pal::SgxAttestationMeasurement& measurement, + const ccf::CodeStatus& status) { + auto digest = ds::to_hex(measurement); out.versions.push_back({digest, status}); return true; }); @@ -275,8 +277,10 @@ namespace ccf auto measurements = ctx.tx.template ro(Tables::NODE_SNP_MEASUREMENTS); measurements->foreach( - [&out](const ccf::CodeDigest& cd, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(cd.data); + [&out]( + const ccf::pal::SnpAttestationMeasurement& measurement, + const ccf::CodeStatus& status) { + auto digest = ds::to_hex(measurement); out.versions.push_back({digest, status}); return true; }); diff --git a/src/node/node_state.h b/src/node/node_state.h index da66cff9125d..682d22a5a7b7 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -474,7 +474,7 @@ namespace ccf launch_node(); }; - pal::attestation_report_data report_data = {}; + pal::AttestationReportData report_data = {}; crypto::Sha256Hash node_pub_key_hash((node_sign_kp->public_key_der())); std::copy( node_pub_key_hash.h.begin(), diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 9247353842aa..d5c4470f249c 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -18,7 +18,13 @@ namespace ccf { case QuoteFormat::oe_sgx_v1: { - auto code_id = tx.ro(Tables::NODE_CODE_IDS)->get(unique_id); + pal::SgxAttestationMeasurement mr; + // TODO: Ugly! + std::copy( + unique_id.data.begin(), + unique_id.data.begin() + mr.size(), + mr.begin()); + auto code_id = tx.ro(Tables::NODE_CODE_IDS)->get(mr); if (!code_id.has_value()) { return QuoteVerificationResult::FailedCodeIdNotFound; @@ -27,8 +33,9 @@ namespace ccf } case QuoteFormat::amd_sev_snp_v1: { + pal::SnpAttestationMeasurement mr = unique_id.data; auto measurement = - tx.ro(Tables::NODE_SNP_MEASUREMENTS)->get(unique_id); + tx.ro(Tables::NODE_SNP_MEASUREMENTS)->get(mr); if (!measurement.has_value()) { return QuoteVerificationResult::FailedCodeIdNotFound; @@ -62,7 +69,7 @@ namespace ccf const QuoteInfo& quote_info) { CodeDigest unique_id = {}; - pal::attestation_report_data r = {}; + pal::AttestationReportData r = {}; try { pal::verify_quote(quote_info, unique_id.data, r); @@ -87,7 +94,7 @@ namespace ccf HostData digest{}; HostData::Representation rep{}; CodeDigest d = {}; - pal::attestation_report_data r = {}; + pal::AttestationReportData r = {}; try { pal::verify_quote(quote_info, d.data, r); @@ -137,7 +144,7 @@ namespace ccf CodeDigest& code_digest) { crypto::Sha256Hash quoted_hash; - pal::attestation_report_data report; + pal::AttestationReportData report; try { pal::verify_quote(quote_info, code_digest.data, report); diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index 6160b9f899e2..e40dee32257b 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -475,87 +475,95 @@ namespace ccf template void add_kv_wrapper_endpoint(T table) { - constexpr bool is_map = nonstd::is_specialization::value; - constexpr bool is_value = - nonstd::is_specialization::value; - - if constexpr (!(is_map || is_value)) - { - static_assert(nonstd::dependent_false_v, "Unsupported table type"); - } - - auto getter = - [&, table](endpoints::ReadOnlyEndpointContext& ctx, nlohmann::json&&) { - LOG_TRACE_FMT("Called getter for {}", table.get_name()); - auto response_body = nlohmann::json::object(); - - auto handle = ctx.tx.template ro(table); - if constexpr (is_map) - { - handle->foreach([&response_body](const auto& k, const auto& v) { - if constexpr ( - std::is_same_v || - std::is_same_v) - { - response_body[k.hex_str()] = v; - } - else - { - response_body[k] = v; - } - return true; - }); - } - else if constexpr (is_value) - { - response_body = handle->get(); - } - - return ccf::make_success(response_body); - }; - - std::string uri = table.get_name(); - constexpr auto gov_prefix = "public:ccf.gov."; - if (uri.starts_with(gov_prefix)) - { - uri.erase(0, strlen(gov_prefix)); - } - else - { - throw std::logic_error(fmt::format( - "Should only be used to wrap governance tables. '{}' is not " - "supported", - uri)); - } - - // Replace . separators with / - { - auto idx = uri.find('.'); - while (idx != std::string::npos) - { - uri[idx] = '/'; - idx = uri.find('.', idx); - } - } - - auto endpoint = make_read_only_endpoint( - fmt::format("/kv/{}", uri), - HTTP_GET, - json_read_only_adapter(getter), - ccf::no_auth_required); - - if constexpr (is_map) - { - endpoint.template set_auto_schema< - void, - std::map>(); - } - else if constexpr (is_value) - { - endpoint.template set_auto_schema(); - } - - endpoint.install(); + // constexpr bool is_map = nonstd::is_specialization::value; constexpr bool is_value = + // nonstd::is_specialization::value; + + // if constexpr (!(is_map || is_value)) + // { + // static_assert(nonstd::dependent_false_v, "Unsupported table + // type"); + // } + + // auto getter = [&, table]( + // endpoints::ReadOnlyEndpointContext& ctx, + // nlohmann::json&&) { + // LOG_TRACE_FMT("Called getter for {}", table.get_name()); + // auto response_body = nlohmann::json::object(); + + // auto handle = ctx.tx.template ro(table); + // if constexpr (is_map) + // { + // handle->foreach([&response_body](const auto& k, const auto& v) { + // if constexpr ( + // std::is_same_v || + // std::is_same_v || + // std::is_same_v< + // typename T::Key, + // ccf::pal::SnpAttestationMeasurement> || + // std:: + // is_same_v) + // { + // response_body[k.hex_str()] = v; + // } + // else + // { + // response_body[k] = v; + // } + // return true; + // }); + // } + // else if constexpr (is_value) + // { + // response_body = handle->get(); + // } + + // return ccf::make_success(response_body); + // }; + + // std::string uri = table.get_name(); + // constexpr auto gov_prefix = "public:ccf.gov."; + // if (uri.starts_with(gov_prefix)) + // { + // uri.erase(0, strlen(gov_prefix)); + // } + // else + // { + // throw std::logic_error(fmt::format( + // "Should only be used to wrap governance tables. '{}' is not " + // "supported", + // uri)); + // } + + // // Replace . separators with / + // { + // auto idx = uri.find('.'); + // while (idx != std::string::npos) + // { + // uri[idx] = '/'; + // idx = uri.find('.', idx); + // } + // } + + // auto endpoint = make_read_only_endpoint( + // fmt::format("/kv/{}", uri), + // HTTP_GET, + // json_read_only_adapter(getter), + // ccf::no_auth_required); + + // if constexpr (is_map) + // { + // endpoint.template set_auto_schema< + // void, + // std::map>(); + // } + // else if constexpr (is_value) + // { + // endpoint.template set_auto_schema(); + // } + + // endpoint.install(); } void add_kv_wrapper_endpoints() diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 58ad5ad9b33d..8b3f105fc881 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -421,14 +421,27 @@ namespace ccf case QuoteFormat::insecure_virtual: case QuoteFormat::oe_sgx_v1: { + pal::SgxAttestationMeasurement mr; + // TODO: Ugly! + std::copy( + node_code_id.data.begin(), + node_code_id.data.begin() + mr.size(), + mr.begin()); tx.rw(Tables::NODE_CODE_IDS) - ->put(node_code_id, CodeStatus::ALLOWED_TO_JOIN); + ->put(mr, CodeStatus::ALLOWED_TO_JOIN); break; } case QuoteFormat::amd_sev_snp_v1: { + pal::SnpAttestationMeasurement mr; + // TODO: Ugly! + std::copy( + node_code_id.data.begin(), + node_code_id.data.begin() + mr.size(), + mr.begin()); + tx.rw(Tables::NODE_SNP_MEASUREMENTS) - ->put(node_code_id, CodeStatus::ALLOWED_TO_JOIN); + ->put(mr, CodeStatus::ALLOWED_TO_JOIN); break; } default: From 055cd3df2ffd6dba2cd83dff6d624ae8754c981a Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 22 Feb 2023 16:18:46 +0000 Subject: [PATCH 03/25] Compiles --- include/ccf/pal/attestation.h | 26 +++++++++++---- include/ccf/pal/attestation_sev_snp.h | 7 ++++ include/ccf/service/code_digest.h | 27 ++++++++------- src/node/node_state.h | 47 ++++++++++++++------------- src/node/quote.cpp | 8 ++--- src/node/rpc/node_frontend.h | 3 +- 6 files changed, 72 insertions(+), 46 deletions(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 9ec4cf138d2a..ef874f21a82b 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -9,6 +9,7 @@ #include "ccf/ds/logger.h" #include "ccf/ds/quote_info.h" #include "ccf/pal/attestation_sev_snp.h" +#include "ccf/service/code_digest.h" #include #include @@ -24,7 +25,7 @@ namespace ccf::pal { // TODO: Change this using AttestationReportData = SnpAttestationReportData; - using AttestationMeasurement = SnpAttestationMeasurement; + // using AttestationMeasurement = SnpAttestationMeasurement; // Caller-supplied callback used to retrieve endorsements as specified by // the config argument. When called back, the quote_info argument will have @@ -37,7 +38,7 @@ namespace ccf::pal // SGX, this does not require external dependencies (Open Enclave for SGX). static void verify_snp_attestation_report( const QuoteInfo& quote_info, - AttestationMeasurement& unique_id, + ccf::CodeDigest& unique_id, AttestationReportData& report_data) { if (quote_info.format != QuoteFormat::amd_sev_snp_v1) @@ -83,10 +84,12 @@ namespace ccf::pal std::begin(quote.report_data), std::end(quote.report_data), report_data.begin()); + + // TODO: Make CodeDigest from snp measurement (assert size!) std::copy( std::begin(quote.measurement), std::end(quote.measurement), - unique_id.begin()); + unique_id.data.begin()); auto certificates = crypto::split_x509_cert_bundle(std::string_view( reinterpret_cast(quote_info.endorsements.data()), @@ -155,7 +158,7 @@ namespace ccf::pal } // We should check this (although not security critical) but the guest - // policy ABI is currently set to 0.31, although we are targetting 1.54 + // policy ABI is currently set to 0.31, although we are targeting 1.54 // if (quote.policy.abi_major < snp::attestation_policy_abi_major) // { // throw std::logic_error(fmt::format( @@ -278,7 +281,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - AttestationMeasurement& unique_id, + ccf::CodeDigest& unique_id, AttestationReportData& report_data) { auto is_sev_snp = access(snp::DEVICE, F_OK) == 0; @@ -381,7 +384,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - AttestationMeasurement& unique_id, + ccf::CodeDigest& unique_id, AttestationReportData& report_data) { if (quote_info.format == QuoteFormat::insecure_virtual) @@ -422,8 +425,17 @@ namespace ccf::pal auto claim_name = std::string(claim.name); if (claim_name == OE_CLAIM_UNIQUE_ID) { + SgxAttestationMeasurement sgx_measurement; + if (claim.value_size != sgx_measurement.size()) + { + throw std::logic_error( + fmt::format("SGX unique ID claim is not of expected size")); + } + std::copy( - claim.value, claim.value + claim.value_size, unique_id.begin()); + claim.value, claim.value + claim.value_size, sgx_measurement.begin()); + unique_id = sgx_measurement; + unique_id_found = true; } else if (claim_name == OE_CLAIM_CUSTOM_CLAIMS_BUFFER) diff --git a/include/ccf/pal/attestation_sev_snp.h b/include/ccf/pal/attestation_sev_snp.h index 7d8163c12a08..13003000ea57 100644 --- a/include/ccf/pal/attestation_sev_snp.h +++ b/include/ccf/pal/attestation_sev_snp.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/pal/attestation_sev_snp_endorsements.h" +#include "ccf/service/code_digest.h" #include #include @@ -20,6 +21,12 @@ namespace ccf::pal using SnpAttestationMeasurement = std::array; + // static ccf::CodeDigest snp_measurement_to_code_digest( + // const SnpAttestationMeasurement& snp_measurement) + // { + // return snp_measurement; + // } + namespace snp { static constexpr auto NO_SECURITY_POLICY = ""; diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index f4348209f4c9..b1b268a28e0e 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -5,28 +5,32 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" #include "ccf/ds/json.h" -#include "ccf/pal/attestation.h" +// #include "ccf/pal/attestation.h" -#if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE) -# include "ccf/pal/attestation_sev_snp.h" -#else -# include "ccf/pal/attestation_sgx.h" -#endif +// // #if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE) +// #include "ccf/pal/attestation_sev_snp.h" +// // #else +// #include "ccf/pal/attestation_sgx.h" +// // #endif namespace ccf { + // Generic wrapper for code digests on all TEE platforms struct CodeDigest { // TODO: Enforce size invariants for SGX and SNP - pal::AttestationMeasurement data; + // TODO: Should this be a vector instead?? + // pal::AttestationMeasurement data; + std::vector data; + // std::array data; CodeDigest() = default; CodeDigest(const CodeDigest&) = default; - // template - // CodeDigest(const std::array& raw_measurement) : - // data(raw_measurement.begin(), raw_measurement.end()) - // {} + // TODO: Needed? + template + CodeDigest(const std::array& raw) : data(raw.begin(), raw.end()) + {} CodeDigest& operator=(const CodeDigest&) = default; @@ -46,6 +50,7 @@ namespace ccf if (j.is_string()) { auto value = j.get(); + code_digest.data.resize(value.size() / 2); ds::from_hex(value, code_digest.data); } else diff --git a/src/node/node_state.h b/src/node/node_state.h index 5adcf4a532f6..3661f8786f8b 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -290,29 +290,7 @@ namespace ccf if (code_id.has_value()) { node_measurement = code_id.value(); - - if (!config.attestation.environment.uvm_endorsements.has_value()) - { - LOG_INFO_FMT( - "UVM endorsements not set, skipping check against attestation " - "measurement"); - } - else - { - try - { - auto uvm_endorsements_raw = crypto::raw_from_b64( - config.attestation.environment.uvm_endorsements.value()); - snp_uvm_endorsements = - verify_uvm_endorsements(uvm_endorsements_raw, node_measurement); - quote_info.uvm_endorsements = uvm_endorsements_raw; - } - catch (const std::exception& e) - { - throw std::logic_error( - fmt::format("Error verifying UVM endorsements: {}", e.what())); - } - } + LOG_FAIL_FMT("Node measurement: {}", node_measurement.hex_str()); } else { @@ -354,6 +332,29 @@ namespace ccf "Successfully verified attested security policy {}", security_policy_digest); } + + if (!config.attestation.environment.uvm_endorsements.has_value()) + { + LOG_INFO_FMT( + "UVM endorsements not set, skipping check against attestation " + "measurement"); + } + else + { + try + { + auto uvm_endorsements_raw = crypto::raw_from_b64( + config.attestation.environment.uvm_endorsements.value()); + snp_uvm_endorsements = + verify_uvm_endorsements(uvm_endorsements_raw, node_measurement); + quote_info.uvm_endorsements = uvm_endorsements_raw; + } + catch (const std::exception& e) + { + throw std::logic_error( + fmt::format("Error verifying UVM endorsements: {}", e.what())); + } + } } switch (start_type) diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 298d482023f3..27b48ba0886d 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -82,7 +82,7 @@ namespace ccf } else { - pal::SnpAttestationMeasurement mr = quote_measurement.data; + pal::SnpAttestationMeasurement mr; // = quote_measurement.data; auto measurement = tx.ro(Tables::NODE_SNP_MEASUREMENTS)->get(mr); if (!measurement.has_value()) @@ -122,7 +122,7 @@ namespace ccf pal::AttestationReportData r = {}; try { - pal::verify_quote(quote_info, measurement.data, r); + pal::verify_quote(quote_info, measurement, r); } catch (const std::exception& e) { @@ -147,7 +147,7 @@ namespace ccf pal::AttestationReportData r = {}; try { - pal::verify_quote(quote_info, d.data, r); + pal::verify_quote(quote_info, d, r); auto quote = *reinterpret_cast( quote_info.quote.data()); std::copy( @@ -197,7 +197,7 @@ namespace ccf pal::AttestationReportData report; try { - pal::verify_quote(quote_info, code_digest.data, report); + pal::verify_quote(quote_info, code_digest, report); // Attestation report may be different sizes depending on the platform. std::copy( diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index cb960857c798..0678d1a202bf 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -1483,6 +1483,7 @@ namespace ccf } const auto in = params.get(); + GenesisGenerator g(this->network, ctx.tx); if (g.is_service_created(in.service_cert)) { @@ -1547,7 +1548,7 @@ namespace ccf in.public_encryption_key, NodeStatus::TRUSTED, std::nullopt, - ds::to_hex(in.code_digest.data), + in.code_digest.hex_str(), in.certificate_signing_request, in.public_key, in.node_data}; From 55c1035b35013f71a7609ee8630b36a2551039e1 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 22 Feb 2023 16:55:04 +0000 Subject: [PATCH 04/25] WIP - refactor --- include/ccf/pal/attestation.h | 8 +- include/ccf/pal/attestation_sgx.h | 17 ++-- include/ccf/pal/measurement.h | 98 ++++++++++++++++++++++ include/ccf/service/code_digest.h | 77 ++++++++--------- src/endpoints/common_endpoint_registry.cpp | 2 +- src/node/quote.cpp | 2 +- src/service/genesis_gen.h | 2 +- 7 files changed, 153 insertions(+), 53 deletions(-) create mode 100644 include/ccf/pal/measurement.h diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index ef874f21a82b..1dcd47a10953 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -25,7 +25,6 @@ namespace ccf::pal { // TODO: Change this using AttestationReportData = SnpAttestationReportData; - // using AttestationMeasurement = SnpAttestationMeasurement; // Caller-supplied callback used to retrieve endorsements as specified by // the config argument. When called back, the quote_info argument will have @@ -425,6 +424,7 @@ namespace ccf::pal auto claim_name = std::string(claim.name); if (claim_name == OE_CLAIM_UNIQUE_ID) { + // TODO: Ugly! SgxAttestationMeasurement sgx_measurement; if (claim.value_size != sgx_measurement.size()) { @@ -433,8 +433,10 @@ namespace ccf::pal } std::copy( - claim.value, claim.value + claim.value_size, sgx_measurement.begin()); - unique_id = sgx_measurement; + claim.value, + claim.value + claim.value_size, + sgx_measurement.data.begin()); + unique_id = sgx_measurement.data; unique_id_found = true; } diff --git a/include/ccf/pal/attestation_sgx.h b/include/ccf/pal/attestation_sgx.h index ad666a063445..c656daa91845 100644 --- a/include/ccf/pal/attestation_sgx.h +++ b/include/ccf/pal/attestation_sgx.h @@ -3,20 +3,23 @@ #pragma once #include -#include -#include -#include -#include + +#if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) +# include +# include +# include +# include +#endif + +#include "ccf/ds/hex.h" +#include "ccf/pal/measurement.h" namespace ccf::pal { static constexpr size_t sgx_attestation_report_data_size = 32; - static constexpr size_t sgx_attestation_measurement_size = 32; using SgxAttestationReportData = std::array; - using SgxAttestationMeasurement = - std::array; #if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h new file mode 100644 index 000000000000..55bb1a135a06 --- /dev/null +++ b/include/ccf/pal/measurement.h @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#pragma once + +#include "ccf/ds/hex.h" + +#include + +namespace ccf::pal +{ + // TODO: + // 1. Same for SNP + // 2. Remove CodeDigest altogether? + // 3. Same for report data? + + static constexpr size_t sgx_attestation_measurement_size = 32; + + template + struct AttestationMeasurement + { + std::array data; + + static size_t size() + { + return N; + } + + AttestationMeasurement() = default; + }; + + template + inline void to_json( + nlohmann::json& j, const AttestationMeasurement& measurement) + { + j = ds::to_hex(measurement.data); + } + + template + inline void from_json( + const nlohmann::json& j, AttestationMeasurement& measurement) + { + if (j.is_string()) + { + auto value = j.get(); + ds::from_hex(value, measurement.data); + } + else + { + throw JsonParseError(fmt::format( + "Attestation measurement should be hex-encoded string: {}", j.dump())); + } + } + + template + inline void fill_json_schema( + nlohmann::json& schema, const AttestationMeasurement*) + { + schema["type"] = "string"; + + // According to the spec, "format is an open value, so you can use any + // formats, even not those defined by the OpenAPI Specification" + // https://swagger.io/docs/specification/data-models/data-types/#format + schema["format"] = "hex"; + schema["pattern"] = + fmt::format("^[a-f0-9]{}$", AttestationMeasurement::size() * 2); + } + + using SgxAttestationMeasurement = + AttestationMeasurement; + + inline std::string schema_name(const SgxAttestationMeasurement*) + { + return "SgxAttestationMeasurement"; + } + +} + +namespace kv::serialisers +{ + template + struct BlitSerialiser> + { + static SerialisedEntry to_serialised( + const ccf::pal::AttestationMeasurement& measurement) + { + auto hex_str = ds::to_hex(measurement.data); + return SerialisedEntry(hex_str.begin(), hex_str.end()); + } + + static ccf::pal::AttestationMeasurement from_serialised( + const SerialisedEntry& data) + { + ccf::pal::AttestationMeasurement ret; + ds::from_hex(std::string(data.data(), data.end()), ret.data); + return ret; + } + }; +} \ No newline at end of file diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index b1b268a28e0e..479abe92ed87 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -5,13 +5,6 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" #include "ccf/ds/json.h" -// #include "ccf/pal/attestation.h" - -// // #if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE) -// #include "ccf/pal/attestation_sev_snp.h" -// // #else -// #include "ccf/pal/attestation_sgx.h" -// // #endif namespace ccf { @@ -39,44 +32,48 @@ namespace ccf return ds::to_hex(data); } }; + DECLARE_JSON_TYPE(CodeDigest); + DECLARE_JSON_REQUIRED_FIELDS(CodeDigest, data); - inline void to_json(nlohmann::json& j, const CodeDigest& code_digest) - { - j = code_digest.hex_str(); - } + // inline void to_json(nlohmann::json& j, const CodeDigest& code_digest) + // { + // j = code_digest.hex_str(); + // } - inline void from_json(const nlohmann::json& j, CodeDigest& code_digest) - { - if (j.is_string()) - { - auto value = j.get(); - code_digest.data.resize(value.size() / 2); - ds::from_hex(value, code_digest.data); - } - else - { - throw JsonParseError( - fmt::format("Code Digest should be hex-encoded string: {}", j.dump())); - } - } + // inline void from_json(const nlohmann::json& j, CodeDigest& code_digest) + // { + // if (j.is_string()) + // { + // auto value = j.get(); + // code_digest.data.resize(value.size() / 2); + // ds::from_hex(value, code_digest.data); + // } + // else + // { + // throw JsonParseError( + // fmt::format("Code Digest should be hex-encoded string: {}", + // j.dump())); + // } + // } - inline std::string schema_name(const CodeDigest*) - { - return "CodeDigest"; - } + // inline std::string schema_name(const CodeDigest*) + // { + // return "CodeDigest"; + // } - inline void fill_json_schema(nlohmann::json& schema, const CodeDigest*) - { - schema["type"] = "string"; + // inline void fill_json_schema(nlohmann::json& schema, const CodeDigest*) + // { + // schema["type"] = "string"; - // According to the spec, "format is an open value, so you can use any - // formats, even not those defined by the OpenAPI Specification" - // https://swagger.io/docs/specification/data-models/data-types/#format - schema["format"] = "hex"; - // NB: We are not specific about the length of the pattern here, because it - // varies by target platform - schema["pattern"] = "^[a-f0-9]+$"; - } + // // According to the spec, "format is an open value, so you can use any + // // formats, even not those defined by the OpenAPI Specification" + // // https://swagger.io/docs/specification/data-models/data-types/#format + // schema["format"] = "hex"; + // // NB: We are not specific about the length of the pattern here, because + // it + // // varies by target platform + // schema["pattern"] = "^[a-f0-9]+$"; + // } enum class CodeStatus { diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 20d8c28a7635..9b764ad15c4d 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -254,7 +254,7 @@ namespace ccf [&out]( const ccf::pal::SgxAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(measurement); + auto digest = ds::to_hex(measurement.data); out.versions.push_back({digest, status}); return true; }); diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 27b48ba0886d..2e801b4a9c62 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -60,7 +60,7 @@ namespace ccf std::copy( quote_measurement.data.begin(), quote_measurement.data.begin() + mr.size(), - mr.begin()); + mr.data.begin()); auto code_id = tx.ro(Tables::NODE_CODE_IDS)->get(mr); if (!tx.ro(Tables::NODE_CODE_IDS)->get(mr).has_value()) { diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 02c0bdaba6f4..95dea5718a87 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -427,7 +427,7 @@ namespace ccf std::copy( node_code_id.data.begin(), node_code_id.data.begin() + mr.size(), - mr.begin()); + mr.data.begin()); tx.rw(Tables::NODE_CODE_IDS) ->put(mr, CodeStatus::ALLOWED_TO_JOIN); break; From 067c958a79dc63ea9b398adc92d178cb7a908b4c Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 11:42:27 +0000 Subject: [PATCH 05/25] Snp --- include/ccf/pal/attestation_sev_snp.h | 11 ++--------- include/ccf/pal/measurement.h | 9 +++++++++ include/ccf/service/tables/snp_measurements.h | 3 +-- src/endpoints/common_endpoint_registry.cpp | 2 +- src/service/genesis_gen.h | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/ccf/pal/attestation_sev_snp.h b/include/ccf/pal/attestation_sev_snp.h index 13003000ea57..c819c1348657 100644 --- a/include/ccf/pal/attestation_sev_snp.h +++ b/include/ccf/pal/attestation_sev_snp.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/pal/attestation_sev_snp_endorsements.h" +#include "ccf/pal/measurement.h" #include "ccf/service/code_digest.h" #include @@ -14,18 +15,10 @@ namespace ccf::pal // Based on the SEV-SNP ABI Spec document at // https://www.amd.com/system/files/TechDocs/56860.pdf static constexpr size_t snp_attestation_report_data_size = 64; - static constexpr size_t snp_attestation_measurement_size = 48; + // static constexpr size_t snp_attestation_measurement_size = 48; using SnpAttestationReportData = std::array; - using SnpAttestationMeasurement = - std::array; - - // static ccf::CodeDigest snp_measurement_to_code_digest( - // const SnpAttestationMeasurement& snp_measurement) - // { - // return snp_measurement; - // } namespace snp { diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index 55bb1a135a06..664deb55b95e 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/ds/hex.h" +#include "ccf/kv/serialisers/blit_serialiser.h" #include @@ -14,6 +15,7 @@ namespace ccf::pal // 3. Same for report data? static constexpr size_t sgx_attestation_measurement_size = 32; + static constexpr size_t snp_attestation_measurement_size = 48; template struct AttestationMeasurement @@ -73,6 +75,13 @@ namespace ccf::pal return "SgxAttestationMeasurement"; } + using SnpAttestationMeasurement = + AttestationMeasurement; + + inline std::string schema_name(const SnpAttestationMeasurement*) + { + return "SnpAttestationMeasurement"; + } } namespace kv::serialisers diff --git a/include/ccf/service/tables/snp_measurements.h b/include/ccf/service/tables/snp_measurements.h index 45b4cbe4526c..5db722bc87fd 100644 --- a/include/ccf/service/tables/snp_measurements.h +++ b/include/ccf/service/tables/snp_measurements.h @@ -2,8 +2,7 @@ // Licensed under the Apache 2.0 License. #pragma once -#include "ccf/pal/attestation_sev_snp.h" -#include "ccf/service/code_digest.h" +#include "ccf/pal/measurement.h" #include "ccf/service/map.h" namespace ccf diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 9b764ad15c4d..4a40e1401fd4 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -280,7 +280,7 @@ namespace ccf [&out]( const ccf::pal::SnpAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(measurement); + auto digest = ds::to_hex(measurement.data); out.versions.push_back({digest, status}); return true; }); diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 95dea5718a87..7182735ae323 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -439,7 +439,7 @@ namespace ccf std::copy( node_code_id.data.begin(), node_code_id.data.begin() + mr.size(), - mr.begin()); + mr.data.begin()); tx.rw(Tables::NODE_SNP_MEASUREMENTS) ->put(mr, CodeStatus::ALLOWED_TO_JOIN); From 4e0f6ab1197558886bed16f4b54516aa233c1a64 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 11:47:05 +0000 Subject: [PATCH 06/25] KV endpoint --- include/ccf/pal/measurement.h | 5 + src/node/rpc/member_frontend.h | 176 ++++++++++++++++----------------- 2 files changed, 92 insertions(+), 89 deletions(-) diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index 664deb55b95e..ab53cbba8d4c 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -27,6 +27,11 @@ namespace ccf::pal return N; } + std::string hex_str() const + { + return ds::to_hex(data); + } + AttestationMeasurement() = default; }; diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index 1a9dca3398e2..dc19849893c9 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -475,95 +475,93 @@ namespace ccf template void add_kv_wrapper_endpoint(T table) { - // constexpr bool is_map = nonstd::is_specialization::value; constexpr bool is_value = - // nonstd::is_specialization::value; - - // if constexpr (!(is_map || is_value)) - // { - // static_assert(nonstd::dependent_false_v, "Unsupported table - // type"); - // } - - // auto getter = [&, table]( - // endpoints::ReadOnlyEndpointContext& ctx, - // nlohmann::json&&) { - // LOG_TRACE_FMT("Called getter for {}", table.get_name()); - // auto response_body = nlohmann::json::object(); - - // auto handle = ctx.tx.template ro(table); - // if constexpr (is_map) - // { - // handle->foreach([&response_body](const auto& k, const auto& v) { - // if constexpr ( - // std::is_same_v || - // std::is_same_v || - // std::is_same_v< - // typename T::Key, - // ccf::pal::SnpAttestationMeasurement> || - // std:: - // is_same_v) - // { - // response_body[k.hex_str()] = v; - // } - // else - // { - // response_body[k] = v; - // } - // return true; - // }); - // } - // else if constexpr (is_value) - // { - // response_body = handle->get(); - // } - - // return ccf::make_success(response_body); - // }; - - // std::string uri = table.get_name(); - // constexpr auto gov_prefix = "public:ccf.gov."; - // if (uri.starts_with(gov_prefix)) - // { - // uri.erase(0, strlen(gov_prefix)); - // } - // else - // { - // throw std::logic_error(fmt::format( - // "Should only be used to wrap governance tables. '{}' is not " - // "supported", - // uri)); - // } - - // // Replace . separators with / - // { - // auto idx = uri.find('.'); - // while (idx != std::string::npos) - // { - // uri[idx] = '/'; - // idx = uri.find('.', idx); - // } - // } - - // auto endpoint = make_read_only_endpoint( - // fmt::format("/kv/{}", uri), - // HTTP_GET, - // json_read_only_adapter(getter), - // ccf::no_auth_required); - - // if constexpr (is_map) - // { - // endpoint.template set_auto_schema< - // void, - // std::map>(); - // } - // else if constexpr (is_value) - // { - // endpoint.template set_auto_schema(); - // } - - // endpoint.install(); + constexpr bool is_map = nonstd::is_specialization::value; + constexpr bool is_value = + nonstd::is_specialization::value; + + if constexpr (!(is_map || is_value)) + { + static_assert(nonstd::dependent_false_v, "Unsupported table type"); + } + + auto getter = [&, table]( + endpoints::ReadOnlyEndpointContext& ctx, + nlohmann::json&&) { + LOG_TRACE_FMT("Called getter for {}", table.get_name()); + auto response_body = nlohmann::json::object(); + + auto handle = ctx.tx.template ro(table); + if constexpr (is_map) + { + handle->foreach([&response_body](const auto& k, const auto& v) { + if constexpr ( + std::is_same_v || + std::is_same_v || + std::is_same_v< + typename T::Key, + ccf::pal::SnpAttestationMeasurement> || + std:: + is_same_v) + { + response_body[k.hex_str()] = v; + } + else + { + response_body[k] = v; + } + return true; + }); + } + else if constexpr (is_value) + { + response_body = handle->get(); + } + + return ccf::make_success(response_body); + }; + + std::string uri = table.get_name(); + constexpr auto gov_prefix = "public:ccf.gov."; + if (uri.starts_with(gov_prefix)) + { + uri.erase(0, strlen(gov_prefix)); + } + else + { + throw std::logic_error(fmt::format( + "Should only be used to wrap governance tables. '{}' is not " + "supported", + uri)); + } + + // Replace . separators with / + { + auto idx = uri.find('.'); + while (idx != std::string::npos) + { + uri[idx] = '/'; + idx = uri.find('.', idx); + } + } + + auto endpoint = make_read_only_endpoint( + fmt::format("/kv/{}", uri), + HTTP_GET, + json_read_only_adapter(getter), + ccf::no_auth_required); + + if constexpr (is_map) + { + endpoint.template set_auto_schema< + void, + std::map>(); + } + else if constexpr (is_value) + { + endpoint.template set_auto_schema(); + } + + endpoint.install(); } void add_kv_wrapper_endpoints() From c9b39487fc6fe2b2c5e3f7271a4b5f0960fd924b Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 11:58:59 +0000 Subject: [PATCH 07/25] Niceness --- include/ccf/pal/measurement.h | 9 +++++ src/node/rpc/member_frontend.h | 62 +++++++++++++++------------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index ab53cbba8d4c..bed87cf2edcd 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -6,6 +6,7 @@ #include "ccf/kv/serialisers/blit_serialiser.h" #include +#include namespace ccf::pal { @@ -87,6 +88,14 @@ namespace ccf::pal { return "SnpAttestationMeasurement"; } + + template + struct is_attestation_measurement : std::false_type + {}; + + template + struct is_attestation_measurement> : std::true_type + {}; } namespace kv::serialisers diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index dc19849893c9..4954d6faa4bb 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -484,41 +484,35 @@ namespace ccf static_assert(nonstd::dependent_false_v, "Unsupported table type"); } - auto getter = [&, table]( - endpoints::ReadOnlyEndpointContext& ctx, - nlohmann::json&&) { - LOG_TRACE_FMT("Called getter for {}", table.get_name()); - auto response_body = nlohmann::json::object(); - - auto handle = ctx.tx.template ro(table); - if constexpr (is_map) - { - handle->foreach([&response_body](const auto& k, const auto& v) { - if constexpr ( - std::is_same_v || - std::is_same_v || - std::is_same_v< - typename T::Key, - ccf::pal::SnpAttestationMeasurement> || - std:: - is_same_v) - { - response_body[k.hex_str()] = v; - } - else - { - response_body[k] = v; - } - return true; - }); - } - else if constexpr (is_value) - { - response_body = handle->get(); - } + auto getter = + [&, table](endpoints::ReadOnlyEndpointContext& ctx, nlohmann::json&&) { + LOG_TRACE_FMT("Called getter for {}", table.get_name()); + auto response_body = nlohmann::json::object(); - return ccf::make_success(response_body); - }; + auto handle = ctx.tx.template ro(table); + if constexpr (is_map) + { + handle->foreach([&response_body](const auto& k, const auto& v) { + if constexpr ( + std::is_same_v || + pal::is_attestation_measurement::value) + { + response_body[k.hex_str()] = v; + } + else + { + response_body[k] = v; + } + return true; + }); + } + else if constexpr (is_value) + { + response_body = handle->get(); + } + + return ccf::make_success(response_body); + }; std::string uri = table.get_name(); constexpr auto gov_prefix = "public:ccf.gov."; From 9ef347464a900e113cc8b9ff0130a7b6dc2b2d85 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 12:02:04 +0000 Subject: [PATCH 08/25] More minor cleanup --- include/ccf/pal/attestation_sev_snp.h | 1 - include/ccf/pal/measurement.h | 2 +- include/ccf/service/code_digest.h | 62 +--------------------- src/endpoints/common_endpoint_registry.cpp | 4 +- 4 files changed, 4 insertions(+), 65 deletions(-) diff --git a/include/ccf/pal/attestation_sev_snp.h b/include/ccf/pal/attestation_sev_snp.h index c819c1348657..c2cd2c10c5bc 100644 --- a/include/ccf/pal/attestation_sev_snp.h +++ b/include/ccf/pal/attestation_sev_snp.h @@ -15,7 +15,6 @@ namespace ccf::pal // Based on the SEV-SNP ABI Spec document at // https://www.amd.com/system/files/TechDocs/56860.pdf static constexpr size_t snp_attestation_report_data_size = 64; - // static constexpr size_t snp_attestation_measurement_size = 48; using SnpAttestationReportData = std::array; diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index bed87cf2edcd..7d5925dbe76f 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -11,7 +11,7 @@ namespace ccf::pal { // TODO: - // 1. Same for SNP + // 1. Same for SNP [DONE] // 2. Remove CodeDigest altogether? // 3. Same for report data? diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 479abe92ed87..83b0f0ff1392 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -35,70 +35,10 @@ namespace ccf DECLARE_JSON_TYPE(CodeDigest); DECLARE_JSON_REQUIRED_FIELDS(CodeDigest, data); - // inline void to_json(nlohmann::json& j, const CodeDigest& code_digest) - // { - // j = code_digest.hex_str(); - // } - - // inline void from_json(const nlohmann::json& j, CodeDigest& code_digest) - // { - // if (j.is_string()) - // { - // auto value = j.get(); - // code_digest.data.resize(value.size() / 2); - // ds::from_hex(value, code_digest.data); - // } - // else - // { - // throw JsonParseError( - // fmt::format("Code Digest should be hex-encoded string: {}", - // j.dump())); - // } - // } - - // inline std::string schema_name(const CodeDigest*) - // { - // return "CodeDigest"; - // } - - // inline void fill_json_schema(nlohmann::json& schema, const CodeDigest*) - // { - // schema["type"] = "string"; - - // // According to the spec, "format is an open value, so you can use any - // // formats, even not those defined by the OpenAPI Specification" - // // https://swagger.io/docs/specification/data-models/data-types/#format - // schema["format"] = "hex"; - // // NB: We are not specific about the length of the pattern here, because - // it - // // varies by target platform - // schema["pattern"] = "^[a-f0-9]+$"; - // } - enum class CodeStatus { ALLOWED_TO_JOIN = 0 }; DECLARE_JSON_ENUM( CodeStatus, {{CodeStatus::ALLOWED_TO_JOIN, "AllowedToJoin"}}); -} - -namespace kv::serialisers -{ - template <> - struct BlitSerialiser - { - static SerialisedEntry to_serialised(const ccf::CodeDigest& code_digest) - { - auto hex_str = ds::to_hex(code_digest.data); - return SerialisedEntry(hex_str.begin(), hex_str.end()); - } - - static ccf::CodeDigest from_serialised(const SerialisedEntry& data) - { - ccf::CodeDigest ret; - ds::from_hex(std::string(data.data(), data.end()), ret.data); - return ret; - } - }; -} +} \ No newline at end of file diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 4a40e1401fd4..6970b0ae1c8a 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -254,7 +254,7 @@ namespace ccf [&out]( const ccf::pal::SgxAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(measurement.data); + auto digest = measurement.to_hex(); out.versions.push_back({digest, status}); return true; }); @@ -280,7 +280,7 @@ namespace ccf [&out]( const ccf::pal::SnpAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = ds::to_hex(measurement.data); + auto digest = measurement.to_hex(); out.versions.push_back({digest, status}); return true; }); From dd3d076397c3d0051a16a672e409a10493d63998 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 12:13:18 +0000 Subject: [PATCH 09/25] More cleanup --- include/ccf/pal/attestation.h | 2 +- include/ccf/service/code_digest.h | 7 ++++--- src/endpoints/common_endpoint_registry.cpp | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 1dcd47a10953..45fb533d5ae1 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -436,7 +436,7 @@ namespace ccf::pal claim.value, claim.value + claim.value_size, sgx_measurement.data.begin()); - unique_id = sgx_measurement.data; + unique_id = sgx_measurement; unique_id_found = true; } diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 83b0f0ff1392..4bcd0dfc5138 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -5,11 +5,12 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" #include "ccf/ds/json.h" +#include "ccf/pal/measurement.h" namespace ccf { // Generic wrapper for code digests on all TEE platforms - struct CodeDigest + struct CodeDigest // TODO: Rename? { // TODO: Enforce size invariants for SGX and SNP // TODO: Should this be a vector instead?? @@ -20,9 +21,9 @@ namespace ccf CodeDigest() = default; CodeDigest(const CodeDigest&) = default; - // TODO: Needed? template - CodeDigest(const std::array& raw) : data(raw.begin(), raw.end()) + CodeDigest(const pal::AttestationMeasurement& measurement) : + data(measurement.data.begin(), measurement.data.end()) {} CodeDigest& operator=(const CodeDigest&) = default; diff --git a/src/endpoints/common_endpoint_registry.cpp b/src/endpoints/common_endpoint_registry.cpp index 6970b0ae1c8a..df04e78f46bc 100644 --- a/src/endpoints/common_endpoint_registry.cpp +++ b/src/endpoints/common_endpoint_registry.cpp @@ -254,7 +254,7 @@ namespace ccf [&out]( const ccf::pal::SgxAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = measurement.to_hex(); + auto digest = measurement.hex_str(); out.versions.push_back({digest, status}); return true; }); @@ -280,7 +280,7 @@ namespace ccf [&out]( const ccf::pal::SnpAttestationMeasurement& measurement, const ccf::CodeStatus& status) { - auto digest = measurement.to_hex(); + auto digest = measurement.hex_str(); out.versions.push_back({digest, status}); return true; }); From a22cc65871a2b7c4ff5014ea2f84a81fa4232c07 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 15:28:41 +0000 Subject: [PATCH 10/25] Type niceness --- include/ccf/pal/attestation.h | 15 ++++----- include/ccf/pal/measurement.h | 55 +++++++++++++++++++++---------- include/ccf/service/code_digest.h | 14 ++++---- src/node/quote.cpp | 2 +- src/service/genesis_gen.h | 21 ++++-------- 5 files changed, 58 insertions(+), 49 deletions(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 45fb533d5ae1..68d8ec65134e 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -424,19 +424,18 @@ namespace ccf::pal auto claim_name = std::string(claim.name); if (claim_name == OE_CLAIM_UNIQUE_ID) { - // TODO: Ugly! - SgxAttestationMeasurement sgx_measurement; - if (claim.value_size != sgx_measurement.size()) + if (claim.value_size != SgxAttestationMeasurement::size()) { throw std::logic_error( fmt::format("SGX unique ID claim is not of expected size")); } - std::copy( - claim.value, - claim.value + claim.value_size, - sgx_measurement.data.begin()); - unique_id = sgx_measurement; + SgxAttestationMeasurement sgx_measurement; + // std::copy( + // claim.value, + // claim.value + claim.value_size, + // sgx_measurement.data.begin()); + unique_id = SgxAttestationMeasurement({claim.value, claim.value_size}); unique_id_found = true; } diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index 7d5925dbe76f..4b8b38de13b5 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -6,22 +6,20 @@ #include "ccf/kv/serialisers/blit_serialiser.h" #include +#include #include namespace ccf::pal { // TODO: // 1. Same for SNP [DONE] - // 2. Remove CodeDigest altogether? + // 2. Remove CodeDigest altogether [DONE] // 3. Same for report data? - static constexpr size_t sgx_attestation_measurement_size = 32; - static constexpr size_t snp_attestation_measurement_size = 48; - template struct AttestationMeasurement { - std::array data; + std::array measurement; static size_t size() { @@ -30,17 +28,42 @@ namespace ccf::pal std::string hex_str() const { - return ds::to_hex(data); + return ds::to_hex(measurement); } AttestationMeasurement() = default; + AttestationMeasurement(const std::string& hex_str) + { + ds::from_hex(hex_str, measurement); + } + AttestationMeasurement(std::span data) + { + if (measurement.size() != size()) + { + throw std::logic_error(fmt::format( + "Cannot initialise AttestationMeasurement with data of size {}, " + "expected {}", + measurement.size(), + size())); + } + + std::copy(data.data(), data.data() + data.size(), measurement.data()); + } }; + template + struct is_attestation_measurement : std::false_type + {}; + + template + struct is_attestation_measurement> : std::true_type + {}; + template inline void to_json( nlohmann::json& j, const AttestationMeasurement& measurement) { - j = ds::to_hex(measurement.data); + j = measurement.hex_str(); } template @@ -49,8 +72,7 @@ namespace ccf::pal { if (j.is_string()) { - auto value = j.get(); - ds::from_hex(value, measurement.data); + measurement = j.get(); } else { @@ -73,6 +95,8 @@ namespace ccf::pal fmt::format("^[a-f0-9]{}$", AttestationMeasurement::size() * 2); } + // SGX + static constexpr size_t sgx_attestation_measurement_size = 32; using SgxAttestationMeasurement = AttestationMeasurement; @@ -81,6 +105,8 @@ namespace ccf::pal return "SgxAttestationMeasurement"; } + // SNP + static constexpr size_t snp_attestation_measurement_size = 48; using SnpAttestationMeasurement = AttestationMeasurement; @@ -89,13 +115,6 @@ namespace ccf::pal return "SnpAttestationMeasurement"; } - template - struct is_attestation_measurement : std::false_type - {}; - - template - struct is_attestation_measurement> : std::true_type - {}; } namespace kv::serialisers @@ -106,7 +125,7 @@ namespace kv::serialisers static SerialisedEntry to_serialised( const ccf::pal::AttestationMeasurement& measurement) { - auto hex_str = ds::to_hex(measurement.data); + auto hex_str = measurement.hex_str(); return SerialisedEntry(hex_str.begin(), hex_str.end()); } @@ -114,7 +133,7 @@ namespace kv::serialisers const SerialisedEntry& data) { ccf::pal::AttestationMeasurement ret; - ds::from_hex(std::string(data.data(), data.end()), ret.data); + ds::from_hex(std::string(data.data(), data.end()), ret.measurement); return ret; } }; diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 4bcd0dfc5138..3300bb2eb77f 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -2,7 +2,6 @@ // Licensed under the Apache 2.0 License. #pragma once -#include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" #include "ccf/ds/json.h" #include "ccf/pal/measurement.h" @@ -10,20 +9,16 @@ namespace ccf { // Generic wrapper for code digests on all TEE platforms - struct CodeDigest // TODO: Rename? + struct CodeDigest { - // TODO: Enforce size invariants for SGX and SNP - // TODO: Should this be a vector instead?? - // pal::AttestationMeasurement data; std::vector data; - // std::array data; CodeDigest() = default; CodeDigest(const CodeDigest&) = default; template CodeDigest(const pal::AttestationMeasurement& measurement) : - data(measurement.data.begin(), measurement.data.end()) + data(measurement.measurement.begin(), measurement.measurement.end()) {} CodeDigest& operator=(const CodeDigest&) = default; @@ -32,6 +27,11 @@ namespace ccf { return ds::to_hex(data); } + + operator std::span() const + { + return data; + } }; DECLARE_JSON_TYPE(CodeDigest); DECLARE_JSON_REQUIRED_FIELDS(CodeDigest, data); diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 2e801b4a9c62..09b331fafe66 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -60,7 +60,7 @@ namespace ccf std::copy( quote_measurement.data.begin(), quote_measurement.data.begin() + mr.size(), - mr.data.begin()); + mr.measurement.begin()); auto code_id = tx.ro(Tables::NODE_CODE_IDS)->get(mr); if (!tx.ro(Tables::NODE_CODE_IDS)->get(mr).has_value()) { diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 7182735ae323..2a3229a0f950 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -422,27 +422,18 @@ namespace ccf case QuoteFormat::insecure_virtual: case QuoteFormat::oe_sgx_v1: { - pal::SgxAttestationMeasurement mr; - // TODO: Ugly! - std::copy( - node_code_id.data.begin(), - node_code_id.data.begin() + mr.size(), - mr.data.begin()); tx.rw(Tables::NODE_CODE_IDS) - ->put(mr, CodeStatus::ALLOWED_TO_JOIN); + ->put( + pal::SgxAttestationMeasurement(node_code_id), + CodeStatus::ALLOWED_TO_JOIN); break; } case QuoteFormat::amd_sev_snp_v1: { - pal::SnpAttestationMeasurement mr; - // TODO: Ugly! - std::copy( - node_code_id.data.begin(), - node_code_id.data.begin() + mr.size(), - mr.data.begin()); - tx.rw(Tables::NODE_SNP_MEASUREMENTS) - ->put(mr, CodeStatus::ALLOWED_TO_JOIN); + ->put( + pal::SnpAttestationMeasurement(node_code_id), + CodeStatus::ALLOWED_TO_JOIN); break; } default: From 4dc476a2ae06a649aa5c658e55d9de7cea15d9b5 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 15:42:56 +0000 Subject: [PATCH 11/25] Cleanup --- include/ccf/pal/attestation.h | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 68d8ec65134e..d546e36bbfe5 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -84,11 +84,7 @@ namespace ccf::pal std::end(quote.report_data), report_data.begin()); - // TODO: Make CodeDigest from snp measurement (assert size!) - std::copy( - std::begin(quote.measurement), - std::end(quote.measurement), - unique_id.data.begin()); + unique_id = SnpAttestationMeasurement(quote.measurement); auto certificates = crypto::split_x509_cert_bundle(std::string_view( reinterpret_cast(quote_info.endorsements.data()), @@ -416,7 +412,7 @@ namespace ccf::pal oe_result_str(rc))); } - bool unique_id_found = false; + std::optional measurement = std::nullopt; bool sgx_report_data_found = false; for (size_t i = 0; i < claims.length; i++) { @@ -430,14 +426,8 @@ namespace ccf::pal fmt::format("SGX unique ID claim is not of expected size")); } - SgxAttestationMeasurement sgx_measurement; - // std::copy( - // claim.value, - // claim.value + claim.value_size, - // sgx_measurement.data.begin()); - unique_id = SgxAttestationMeasurement({claim.value, claim.value_size}); - - unique_id_found = true; + measurement = + SgxAttestationMeasurement({claim.value, claim.value_size}); } else if (claim_name == OE_CLAIM_CUSTOM_CLAIMS_BUFFER) { @@ -480,7 +470,7 @@ namespace ccf::pal } } - if (!unique_id_found) + if (!measurement.has_value()) { throw std::logic_error( "Could not find measurement in SGX attestation report"); @@ -491,6 +481,8 @@ namespace ccf::pal throw std::logic_error( "Could not find report data in SGX attestation report"); } + + unique_id = measurement.value(); } #endif From 17b2bc62a587e47a0ab57998bba0b7e91feadadd Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 17:20:17 +0000 Subject: [PATCH 12/25] Report data --- .snpcc_canary | 2 +- include/ccf/pal/attestation.h | 45 ++- include/ccf/pal/attestation_sev_snp.h | 405 +++++++++++++------------- include/ccf/pal/attestation_sgx.h | 15 +- include/ccf/pal/measurement.h | 9 +- include/ccf/pal/report_data.h | 71 +++++ include/ccf/service/code_digest.h | 1 + src/crypto/sha256_hash.cpp | 1 + src/node/node_state.h | 9 +- src/node/quote.cpp | 15 +- 10 files changed, 304 insertions(+), 269 deletions(-) create mode 100644 include/ccf/pal/report_data.h diff --git a/.snpcc_canary b/.snpcc_canary index 28b4716e9633..eb818820510d 100644 --- a/.snpcc_canary +++ b/.snpcc_canary @@ -1,4 +1,4 @@ ___ ___ ___ - (O o) Y (9 3) (* *) Y + (O =) Y (9 3) (* *) Y O / O O / /-xXx--//-----xXx--/-xXx--/---x---->xxxxxx diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index d546e36bbfe5..46fbd6dc327c 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -23,9 +23,6 @@ namespace ccf::pal { - // TODO: Change this - using AttestationReportData = SnpAttestationReportData; - // Caller-supplied callback used to retrieve endorsements as specified by // the config argument. When called back, the quote_info argument will have // already been populated with the raw quote. @@ -38,7 +35,7 @@ namespace ccf::pal static void verify_snp_attestation_report( const QuoteInfo& quote_info, ccf::CodeDigest& unique_id, - AttestationReportData& report_data) + PlatformAttestationReportData& report_data) { if (quote_info.format != QuoteFormat::amd_sev_snp_v1) { @@ -79,11 +76,7 @@ namespace ccf::pal fmt::format("SEV-SNP: Mask chip key must not be set")); } - std::copy( - std::begin(quote.report_data), - std::end(quote.report_data), - report_data.begin()); - + report_data = SnpAttestationReportData(quote.report_data); unique_id = SnpAttestationMeasurement(quote.measurement); auto certificates = crypto::split_x509_cert_bundle(std::string_view( @@ -204,7 +197,7 @@ namespace ccf::pal #if defined(PLATFORM_VIRTUAL) static void generate_quote( - AttestationReportData& report_data, + PlatformAttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -218,7 +211,7 @@ namespace ccf::pal #elif defined(PLATFORM_SNP) static void generate_quote( - AttestationReportData& report_data, + PlatformAttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -277,7 +270,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, ccf::CodeDigest& unique_id, - AttestationReportData& report_data) + PlatformAttestationReportData& report_data) { auto is_sev_snp = access(snp::DEVICE, F_OK) == 0; @@ -319,7 +312,7 @@ namespace ccf::pal #else // SGX static void generate_quote( - AttestationReportData& report_data, + PlatformAttestationReportData& report_data, RetrieveEndorsementCallback endorsement_cb, const snp::EndorsementsServers& endorsements_servers = {}) { @@ -334,8 +327,8 @@ namespace ccf::pal const size_t custom_claim_length = 1; oe_claim_t custom_claim; custom_claim.name = const_cast(sgx::report_data_claim_name); - custom_claim.value = report_data.data(); - custom_claim.value_size = report_data.size(); + custom_claim.value = report_data.data.data(); + custom_claim.value_size = report_data.data.size(); auto rc = oe_serialize_custom_claims( &custom_claim, @@ -380,7 +373,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, ccf::CodeDigest& unique_id, - AttestationReportData& report_data) + PlatformAttestationReportData& report_data) { if (quote_info.format == QuoteFormat::insecure_virtual) { @@ -413,7 +406,8 @@ namespace ccf::pal } std::optional measurement = std::nullopt; - bool sgx_report_data_found = false; + std::optional custom_claim_report_data = + std::nullopt; for (size_t i = 0; i < claims.length; i++) { auto& claim = claims.data[i]; @@ -450,20 +444,18 @@ namespace ccf::pal auto& custom_claim = custom_claims.data[j]; if (std::string(custom_claim.name) == sgx::report_data_claim_name) { - if (custom_claim.value_size != report_data.size()) + if (custom_claim.value_size != SgxAttestationReportData::size()) { throw std::logic_error(fmt::format( - "Expected {} of size {}, had size {}", + "Expected claim {} of size {}, had size {}", sgx::report_data_claim_name, - report_data.size(), + SgxAttestationReportData::size(), custom_claim.value_size)); } - std::copy( - custom_claim.value, - custom_claim.value + custom_claim.value_size, - report_data.begin()); - sgx_report_data_found = true; + custom_claim_report_data = SgxAttestationReportData( + {custom_claim.value, custom_claim.value_size}); + break; } } @@ -476,13 +468,14 @@ namespace ccf::pal "Could not find measurement in SGX attestation report"); } - if (!sgx_report_data_found) + if (!custom_claim_report_data.has_value()) { throw std::logic_error( "Could not find report data in SGX attestation report"); } unique_id = measurement.value(); + report_data = custom_claim_report_data.value(); } #endif diff --git a/include/ccf/pal/attestation_sev_snp.h b/include/ccf/pal/attestation_sev_snp.h index c2cd2c10c5bc..0920567c149e 100644 --- a/include/ccf/pal/attestation_sev_snp.h +++ b/include/ccf/pal/attestation_sev_snp.h @@ -4,28 +4,22 @@ #include "ccf/pal/attestation_sev_snp_endorsements.h" #include "ccf/pal/measurement.h" -#include "ccf/service/code_digest.h" +#include "ccf/pal/report_data.h" #include #include #include -namespace ccf::pal +namespace ccf::pal::snp { // Based on the SEV-SNP ABI Spec document at // https://www.amd.com/system/files/TechDocs/56860.pdf - static constexpr size_t snp_attestation_report_data_size = 64; - using SnpAttestationReportData = - std::array; + static constexpr auto NO_SECURITY_POLICY = ""; - namespace snp - { - static constexpr auto NO_SECURITY_POLICY = ""; - - // From https://developer.amd.com/sev/ - constexpr auto amd_milan_root_signing_public_key = - R"(-----BEGIN PUBLIC KEY----- + // From https://developer.amd.com/sev/ + constexpr auto amd_milan_root_signing_public_key = + R"(-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsV mD7FktuotWwX1fNgW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU 0V5tkKiU1EesNFta1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S @@ -42,239 +36,236 @@ QPHfbkH0CyPfhl1jWhJFZasCAwEAAQ== )"; #pragma pack(push, 1) - // Table 3 - struct TcbVersion - { - uint8_t boot_loader; - uint8_t tee; - uint8_t reserved[4]; - uint8_t snp; - uint8_t microcode; + // Table 3 + struct TcbVersion + { + uint8_t boot_loader; + uint8_t tee; + uint8_t reserved[4]; + uint8_t snp; + uint8_t microcode; - bool operator==(const TcbVersion&) const = default; - }; + bool operator==(const TcbVersion&) const = default; + }; #pragma pack(pop) - static_assert( - sizeof(TcbVersion) == sizeof(uint64_t), - "Can't cast TcbVersion to uint64_t"); + static_assert( + sizeof(TcbVersion) == sizeof(uint64_t), + "Can't cast TcbVersion to uint64_t"); #pragma pack(push, 1) - struct Signature - { - uint8_t r[72]; - uint8_t s[72]; - uint8_t reserved[512 - 144]; - }; + struct Signature + { + uint8_t r[72]; + uint8_t s[72]; + uint8_t reserved[512 - 144]; + }; #pragma pack(pop) - // Table 105 - enum class SignatureAlgorithm : uint32_t - { - invalid = 0, - ecdsa_p384_sha384 = 1 - }; + // Table 105 + enum class SignatureAlgorithm : uint32_t + { + invalid = 0, + ecdsa_p384_sha384 = 1 + }; #pragma pack(push, 1) - // Table 8 - struct GuestPolicy - { - uint8_t abi_minor; - uint8_t abi_major; - uint8_t smt : 1; - uint8_t reserved : 1; - uint8_t migrate_ma : 1; - uint8_t debug : 1; - uint8_t single_socket : 1; - uint64_t reserved2 : 43; - }; + // Table 8 + struct GuestPolicy + { + uint8_t abi_minor; + uint8_t abi_major; + uint8_t smt : 1; + uint8_t reserved : 1; + uint8_t migrate_ma : 1; + uint8_t debug : 1; + uint8_t single_socket : 1; + uint64_t reserved2 : 43; + }; #pragma pack(pop) - static_assert( - sizeof(GuestPolicy) == sizeof(uint64_t), - "Can't cast GuestPolicy to uint64_t"); + static_assert( + sizeof(GuestPolicy) == sizeof(uint64_t), + "Can't cast GuestPolicy to uint64_t"); - static constexpr uint8_t attestation_flags_signing_key_vcek = 0; + static constexpr uint8_t attestation_flags_signing_key_vcek = 0; #pragma pack(push, 1) - struct Flags - { - uint8_t author_key_en : 1; - uint8_t mask_chip_key : 1; - uint8_t signing_key : 3; - uint64_t reserved : 27; - }; + struct Flags + { + uint8_t author_key_en : 1; + uint8_t mask_chip_key : 1; + uint8_t signing_key : 3; + uint64_t reserved : 27; + }; #pragma pack(pop) - static_assert( - sizeof(Flags) == sizeof(uint32_t), "Can't cast Flags to uint32_t"); + static_assert( + sizeof(Flags) == sizeof(uint32_t), "Can't cast Flags to uint32_t"); #pragma pack(push, 1) - // Table 22 - struct PlatformInfo - { - uint8_t smt_en : 1; - uint8_t tsme_en : 1; - uint64_t reserved : 62; - }; + // Table 22 + struct PlatformInfo + { + uint8_t smt_en : 1; + uint8_t tsme_en : 1; + uint64_t reserved : 62; + }; #pragma pack(pop) - static_assert( - sizeof(PlatformInfo) == sizeof(uint64_t), - "Can't cast PlatformInfo to uint64_t"); + static_assert( + sizeof(PlatformInfo) == sizeof(uint64_t), + "Can't cast PlatformInfo to uint64_t"); #pragma pack(push, 1) - // Table 21 + // Table 21 - static constexpr uint32_t attestation_version = 2; - static constexpr uint32_t attestation_policy_abi_major = 1; + static constexpr uint32_t attestation_version = 2; + static constexpr uint32_t attestation_policy_abi_major = 1; - struct Attestation - { - uint32_t version; /* 0x000 */ - uint32_t guest_svn; /* 0x004 */ - struct GuestPolicy policy; /* 0x008 */ - uint8_t family_id[16]; /* 0x010 */ - uint8_t image_id[16]; /* 0x020 */ - uint32_t vmpl; /* 0x030 */ - SignatureAlgorithm signature_algo; /* 0x034 */ - struct TcbVersion platform_version; /* 0x038 */ - PlatformInfo platform_info; /* 0x040 */ - Flags flags; /* 0x048 */ - uint32_t reserved0; /* 0x04C */ - uint8_t report_data[snp_attestation_report_data_size]; /* 0x050 */ - uint8_t measurement[snp_attestation_measurement_size]; /* 0x090 */ - uint8_t host_data[32]; /* 0x0C0 */ - uint8_t id_key_digest[48]; /* 0x0E0 */ - uint8_t author_key_digest[48]; /* 0x110 */ - uint8_t report_id[32]; /* 0x140 */ - uint8_t report_id_ma[32]; /* 0x160 */ - struct TcbVersion reported_tcb; /* 0x180 */ - uint8_t reserved1[24]; /* 0x188 */ - uint8_t chip_id[64]; /* 0x1A0 */ - struct TcbVersion committed_tcb; /* 0x1E0 */ - uint8_t current_minor; /* 0x1E8 */ - uint8_t current_build; /* 0x1E9 */ - uint8_t current_major; /* 0x1EA */ - uint8_t reserved2; /* 0x1EB */ - uint8_t committed_build; /* 0x1EC */ - uint8_t committed_minor; /* 0x1ED */ - uint8_t committed_major; /* 0x1EE */ - uint8_t reserved3; /* 0x1EF */ - struct TcbVersion launch_tcb; /* 0x1F0 */ - uint8_t reserved4[168]; /* 0x1F8 */ - struct Signature signature; /* 0x2A0 */ - }; + struct Attestation + { + uint32_t version; /* 0x000 */ + uint32_t guest_svn; /* 0x004 */ + struct GuestPolicy policy; /* 0x008 */ + uint8_t family_id[16]; /* 0x010 */ + uint8_t image_id[16]; /* 0x020 */ + uint32_t vmpl; /* 0x030 */ + SignatureAlgorithm signature_algo; /* 0x034 */ + struct TcbVersion platform_version; /* 0x038 */ + PlatformInfo platform_info; /* 0x040 */ + Flags flags; /* 0x048 */ + uint32_t reserved0; /* 0x04C */ + uint8_t report_data[snp_attestation_report_data_size]; /* 0x050 */ + uint8_t measurement[snp_attestation_measurement_size]; /* 0x090 */ + uint8_t host_data[32]; /* 0x0C0 */ + uint8_t id_key_digest[48]; /* 0x0E0 */ + uint8_t author_key_digest[48]; /* 0x110 */ + uint8_t report_id[32]; /* 0x140 */ + uint8_t report_id_ma[32]; /* 0x160 */ + struct TcbVersion reported_tcb; /* 0x180 */ + uint8_t reserved1[24]; /* 0x188 */ + uint8_t chip_id[64]; /* 0x1A0 */ + struct TcbVersion committed_tcb; /* 0x1E0 */ + uint8_t current_minor; /* 0x1E8 */ + uint8_t current_build; /* 0x1E9 */ + uint8_t current_major; /* 0x1EA */ + uint8_t reserved2; /* 0x1EB */ + uint8_t committed_build; /* 0x1EC */ + uint8_t committed_minor; /* 0x1ED */ + uint8_t committed_major; /* 0x1EE */ + uint8_t reserved3; /* 0x1EF */ + struct TcbVersion launch_tcb; /* 0x1F0 */ + uint8_t reserved4[168]; /* 0x1F8 */ + struct Signature signature; /* 0x2A0 */ + }; #pragma pack(pop) - // Table 20 - struct AttestationReq - { - uint8_t report_data[snp_attestation_report_data_size]; - uint32_t vmpl; - uint8_t reserved[28]; - }; + // Table 20 + struct AttestationReq + { + uint8_t report_data[snp_attestation_report_data_size]; + uint32_t vmpl; + uint8_t reserved[28]; + }; - // Table 23 + // Table 23 #pragma pack(push, 1) - struct AttestationResp - { - uint32_t status; - uint32_t report_size; - uint8_t reserved[0x20 - 0x8]; - struct Attestation report; - uint8_t padding[64]; - // padding to the size of SEV_SNP_REPORT_RSP_BUF_SZ (i.e., 1280 bytes) - }; + struct AttestationResp + { + uint32_t status; + uint32_t report_size; + uint8_t reserved[0x20 - 0x8]; + struct Attestation report; + uint8_t padding[64]; + // padding to the size of SEV_SNP_REPORT_RSP_BUF_SZ (i.e., 1280 bytes) + }; #pragma pack(pop) - struct GuestRequest - { - uint8_t req_msg_type; - uint8_t rsp_msg_type; - uint8_t msg_version; - uint16_t request_len; - uint64_t request_uaddr; - uint16_t response_len; - uint64_t response_uaddr; - uint32_t error; /* firmware error code on failure (see psp-sev.h) */ - }; + struct GuestRequest + { + uint8_t req_msg_type; + uint8_t rsp_msg_type; + uint8_t msg_version; + uint16_t request_len; + uint64_t request_uaddr; + uint16_t response_len; + uint64_t response_uaddr; + uint32_t error; /* firmware error code on failure (see psp-sev.h) */ + }; - // Table 99 - enum MsgType - { - MSG_TYPE_INVALID = 0, - MSG_CPUID_REQ, - MSG_CPUID_RSP, - MSG_KEY_REQ, - MSG_KEY_RSP, - MSG_REPORT_REQ, - MSG_REPORT_RSP, - MSG_EXPORT_REQ, - MSG_EXPORT_RSP, - MSG_IMPORT_REQ, - MSG_IMPORT_RSP, - MSG_ABSORB_REQ, - MSG_ABSORB_RSP, - MSG_VMRK_REQ, - MSG_VMRK_RSP, - MSG_TYPE_MAX - }; + // Table 99 + enum MsgType + { + MSG_TYPE_INVALID = 0, + MSG_CPUID_REQ, + MSG_CPUID_RSP, + MSG_KEY_REQ, + MSG_KEY_RSP, + MSG_REPORT_REQ, + MSG_REPORT_RSP, + MSG_EXPORT_REQ, + MSG_EXPORT_RSP, + MSG_IMPORT_REQ, + MSG_IMPORT_RSP, + MSG_ABSORB_REQ, + MSG_ABSORB_RSP, + MSG_VMRK_REQ, + MSG_VMRK_RSP, + MSG_TYPE_MAX + }; - // Changes on 5.19+ kernel - constexpr auto DEVICE = "/dev/sev"; + // Changes on 5.19+ kernel + constexpr auto DEVICE = "/dev/sev"; - static EndorsementEndpointsConfiguration - make_endorsement_endpoint_configuration( - const Attestation& quote, - const snp::EndorsementsServers& endorsements_servers = {}) - { - EndorsementEndpointsConfiguration config; + static EndorsementEndpointsConfiguration + make_endorsement_endpoint_configuration( + const Attestation& quote, + const snp::EndorsementsServers& endorsements_servers = {}) + { + EndorsementEndpointsConfiguration config; - auto chip_id_hex = fmt::format("{:02x}", fmt::join(quote.chip_id, "")); - auto reported_tcb = - fmt::format("{:0x}", *(uint64_t*)("e.reported_tcb)); + auto chip_id_hex = fmt::format("{:02x}", fmt::join(quote.chip_id, "")); + auto reported_tcb = fmt::format("{:0x}", *(uint64_t*)("e.reported_tcb)); - if (endorsements_servers.empty()) - { - // Default to Azure server if no servers are specified - config.servers.emplace_back(make_azure_endorsements_server( - default_azure_endorsements_endpoint_host, chip_id_hex, reported_tcb)); - return config; - } + if (endorsements_servers.empty()) + { + // Default to Azure server if no servers are specified + config.servers.emplace_back(make_azure_endorsements_server( + default_azure_endorsements_endpoint_host, chip_id_hex, reported_tcb)); + return config; + } - for (auto const& server : endorsements_servers) + for (auto const& server : endorsements_servers) + { + switch (server.type) { - switch (server.type) + case EndorsementsEndpointType::Azure: { - case EndorsementsEndpointType::Azure: - { - auto url = - server.url.value_or(default_azure_endorsements_endpoint_host); - config.servers.emplace_back( - make_azure_endorsements_server(url, chip_id_hex, reported_tcb)); - break; - } - case EndorsementsEndpointType::AMD: - { - auto boot_loader = - fmt::format("{}", quote.reported_tcb.boot_loader); - auto tee = fmt::format("{}", quote.reported_tcb.tee); - auto snp = fmt::format("{}", quote.reported_tcb.snp); - auto microcode = fmt::format("{}", quote.reported_tcb.microcode); + auto url = + server.url.value_or(default_azure_endorsements_endpoint_host); + config.servers.emplace_back( + make_azure_endorsements_server(url, chip_id_hex, reported_tcb)); + break; + } + case EndorsementsEndpointType::AMD: + { + auto boot_loader = fmt::format("{}", quote.reported_tcb.boot_loader); + auto tee = fmt::format("{}", quote.reported_tcb.tee); + auto snp = fmt::format("{}", quote.reported_tcb.snp); + auto microcode = fmt::format("{}", quote.reported_tcb.microcode); - auto url = - server.url.value_or(default_azure_endorsements_endpoint_host); - config.servers.emplace_back(make_amd_endorsements_server( - url, chip_id_hex, boot_loader, tee, snp, microcode)); - break; - } - default: - { - throw std::logic_error(fmt::format( - "Unsupported endorsements server type: {}", server.type)); - } + auto url = + server.url.value_or(default_azure_endorsements_endpoint_host); + config.servers.emplace_back(make_amd_endorsements_server( + url, chip_id_hex, boot_loader, tee, snp, microcode)); + break; + } + default: + { + throw std::logic_error(fmt::format( + "Unsupported endorsements server type: {}", server.type)); } } - - return config; } + + return config; } #define SEV_GUEST_IOC_TYPE 'S' diff --git a/include/ccf/pal/attestation_sgx.h b/include/ccf/pal/attestation_sgx.h index c656daa91845..8ad31ae69033 100644 --- a/include/ccf/pal/attestation_sgx.h +++ b/include/ccf/pal/attestation_sgx.h @@ -5,24 +5,17 @@ #include #if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) +# include "ccf/ds/hex.h" +# include "ccf/pal/measurement.h" +# include "ccf/pal/report_data.h" + # include # include # include # include -#endif - -#include "ccf/ds/hex.h" -#include "ccf/pal/measurement.h" namespace ccf::pal { - static constexpr size_t sgx_attestation_report_data_size = 32; - - using SgxAttestationReportData = - std::array; - -#if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) - namespace sgx { // Set of wrappers for safe memory management diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index 4b8b38de13b5..e91babf17250 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -11,11 +11,6 @@ namespace ccf::pal { - // TODO: - // 1. Same for SNP [DONE] - // 2. Remove CodeDigest altogether [DONE] - // 3. Same for report data? - template struct AttestationMeasurement { @@ -38,12 +33,12 @@ namespace ccf::pal } AttestationMeasurement(std::span data) { - if (measurement.size() != size()) + if (data.size() != size()) { throw std::logic_error(fmt::format( "Cannot initialise AttestationMeasurement with data of size {}, " "expected {}", - measurement.size(), + data.size(), size())); } diff --git a/include/ccf/pal/report_data.h b/include/ccf/pal/report_data.h new file mode 100644 index 000000000000..476a3882ee96 --- /dev/null +++ b/include/ccf/pal/report_data.h @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#pragma once + +#include "ccf/crypto/sha256_hash.h" + +#include +#include +#include + +namespace ccf::pal +{ + template + struct AttestationReportData + { + std::array report_data; + + static size_t size() + { + return N; + } + + AttestationReportData() = default; + AttestationReportData(std::span data) + { + if (data.size() != size()) + { + throw std::logic_error(fmt::format( + "Cannot initialise AttestationReportData with data of size {}, " + "expected {}", + data.size(), + size())); + } + + std::copy(data.data(), data.data() + data.size(), report_data.data()); + } + }; + + struct PlatformAttestationReportData + { + std::vector data; + + PlatformAttestationReportData() = default; + + PlatformAttestationReportData(const crypto::Sha256Hash& hash) : + data(hash.h.begin(), hash.h.end()) + {} + + template + PlatformAttestationReportData(const AttestationReportData& report_data) : + data(report_data.report_data.begin(), report_data.report_data.end()) + {} + + crypto::Sha256Hash to_sha256_hash() const + { + return crypto::Sha256Hash::from_span( + {data.data(), crypto::Sha256Hash::SIZE}); + } + }; + + // SGX + static constexpr size_t sgx_attestation_report_data_size = 32; + using SgxAttestationReportData = + AttestationReportData; + + // SNP + static constexpr size_t snp_attestation_report_data_size = 64; + using SnpAttestationReportData = + AttestationReportData; + +} \ No newline at end of file diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 3300bb2eb77f..3b005c4ff7c5 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -9,6 +9,7 @@ namespace ccf { // Generic wrapper for code digests on all TEE platforms + // TODO: Rename and make private? struct CodeDigest { std::vector data; diff --git a/src/crypto/sha256_hash.cpp b/src/crypto/sha256_hash.cpp index 10b8125523b8..c101162ce4d2 100644 --- a/src/crypto/sha256_hash.cpp +++ b/src/crypto/sha256_hash.cpp @@ -4,6 +4,7 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" +#include "ccf/ds/logger.h" namespace crypto { diff --git a/src/node/node_state.h b/src/node/node_state.h index 3661f8786f8b..24f61587423a 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -290,7 +290,6 @@ namespace ccf if (code_id.has_value()) { node_measurement = code_id.value(); - LOG_FAIL_FMT("Node measurement: {}", node_measurement.hex_str()); } else { @@ -477,12 +476,8 @@ namespace ccf launch_node(); }; - pal::AttestationReportData report_data = {}; - crypto::Sha256Hash node_pub_key_hash((node_sign_kp->public_key_der())); - std::copy( - node_pub_key_hash.h.begin(), - node_pub_key_hash.h.end(), - report_data.begin()); + pal::PlatformAttestationReportData report_data = + crypto::Sha256Hash((node_sign_kp->public_key_der())); pal::generate_quote( report_data, diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 09b331fafe66..6bfc5e8be841 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -119,7 +119,7 @@ namespace ccf const QuoteInfo& quote_info) { CodeDigest measurement = {}; - pal::AttestationReportData r = {}; + pal::PlatformAttestationReportData r = {}; try { pal::verify_quote(quote_info, measurement, r); @@ -144,7 +144,7 @@ namespace ccf HostData digest{}; HostData::Representation rep{}; CodeDigest d = {}; - pal::AttestationReportData r = {}; + pal::PlatformAttestationReportData r = {}; try { pal::verify_quote(quote_info, d, r); @@ -194,16 +194,11 @@ namespace ccf CodeDigest& code_digest) { crypto::Sha256Hash quoted_hash; - pal::AttestationReportData report; + pal::PlatformAttestationReportData report_data; try { - pal::verify_quote(quote_info, code_digest, report); - - // Attestation report may be different sizes depending on the platform. - std::copy( - report.begin(), - report.begin() + crypto::Sha256Hash::SIZE, - quoted_hash.h.begin()); + pal::verify_quote(quote_info, code_digest, report_data); + quoted_hash = report_data.to_sha256_hash(); } catch (const std::exception& e) { From 76a2c29cd88efb67765677442c73ed5e645dccc1 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 27 Feb 2023 17:29:55 +0000 Subject: [PATCH 13/25] Self-review --- include/ccf/pal/attestation_sgx.h | 10 +++------- src/node/quote.cpp | 18 ++++++------------ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/include/ccf/pal/attestation_sgx.h b/include/ccf/pal/attestation_sgx.h index 8ad31ae69033..b71729925ca4 100644 --- a/include/ccf/pal/attestation_sgx.h +++ b/include/ccf/pal/attestation_sgx.h @@ -2,13 +2,9 @@ // Licensed under the Apache 2.0 License. #pragma once -#include - #if defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE) -# include "ccf/ds/hex.h" -# include "ccf/pal/measurement.h" -# include "ccf/pal/report_data.h" +# include # include # include # include @@ -77,5 +73,5 @@ namespace ccf::pal static constexpr oe_uuid_t oe_quote_format = {OE_FORMAT_UUID_SGX_ECDSA}; static constexpr auto report_data_claim_name = OE_CLAIM_SGX_REPORT_DATA; } -#endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/node/quote.cpp b/src/node/quote.cpp index 6bfc5e8be841..e9e6f66bfbfb 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -55,14 +55,9 @@ namespace ccf { case QuoteFormat::oe_sgx_v1: { - pal::SgxAttestationMeasurement mr; - // TODO: Ugly! - std::copy( - quote_measurement.data.begin(), - quote_measurement.data.begin() + mr.size(), - mr.measurement.begin()); - auto code_id = tx.ro(Tables::NODE_CODE_IDS)->get(mr); - if (!tx.ro(Tables::NODE_CODE_IDS)->get(mr).has_value()) + if (!tx.ro(Tables::NODE_CODE_IDS) + ->get(pal::SgxAttestationMeasurement(quote_measurement)) + .has_value()) { return QuoteVerificationResult::FailedMeasurementNotFound; } @@ -82,10 +77,9 @@ namespace ccf } else { - pal::SnpAttestationMeasurement mr; // = quote_measurement.data; - auto measurement = - tx.ro(Tables::NODE_SNP_MEASUREMENTS)->get(mr); - if (!measurement.has_value()) + if (!tx.ro(Tables::NODE_SNP_MEASUREMENTS) + ->get(pal::SnpAttestationMeasurement(quote_measurement)) + .has_value()) { return QuoteVerificationResult::FailedMeasurementNotFound; } From 879371e06cf8bed467be284e31c35cb042ceefcf Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 09:23:42 +0000 Subject: [PATCH 14/25] Fix build --- src/service/genesis_gen.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 2a3229a0f950..93ec2cd07a16 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/crypto/verifier.h" +#include "ccf/pal/attestation_sev_snp.h" #include "ccf/service/tables/code_id.h" #include "ccf/service/tables/members.h" #include "ccf/service/tables/nodes.h" From 9d6d998bf28382eeed128bb2c50b7fb5076210ee Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 09:27:26 +0000 Subject: [PATCH 15/25] External executor SNP measurement --- src/apps/external_executor/executor_code_id.h | 4 +++- src/apps/external_executor/external_executor.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/apps/external_executor/executor_code_id.h b/src/apps/external_executor/executor_code_id.h index db085c1eda66..94fa0ca1963a 100644 --- a/src/apps/external_executor/executor_code_id.h +++ b/src/apps/external_executor/executor_code_id.h @@ -4,6 +4,7 @@ #include "ccf/ds/json.h" #include "ccf/node/quote.h" +#include "ccf/pal/attestation_sev_snp.h" #include "ccf/service/code_digest.h" #include "ccf/service/map.h" #include "ccf/service/tables/code_id.h" @@ -92,7 +93,8 @@ namespace externalexecutor DECLARE_JSON_TYPE(ExecutorCodeInfo); DECLARE_JSON_REQUIRED_FIELDS(ExecutorCodeInfo, status, platform); - using ExecutorCodeIDs = ccf::ServiceMap; + using ExecutorCodeIDs = + ccf::ServiceMap; static constexpr auto EXECUTOR_CODE_IDS = "public:ccf.gov.nodes.executor_code_ids"; diff --git a/src/apps/external_executor/external_executor.cpp b/src/apps/external_executor/external_executor.cpp index 75658f54c517..565f50139a08 100644 --- a/src/apps/external_executor/external_executor.cpp +++ b/src/apps/external_executor/external_executor.cpp @@ -306,8 +306,10 @@ namespace externalexecutor auto executor_code_ids = ctx.tx.template ro(EXECUTOR_CODE_IDS); executor_code_ids->foreach( - [&out](const ccf::CodeDigest& cd, const ExecutorCodeInfo& info) { - auto digest = ds::to_hex(cd.data); + [&out]( + const ccf::pal::SnpAttestationMeasurement& measurement, + const ExecutorCodeInfo& info) { + auto digest = measurement.hex_str(); out.versions.push_back({digest, info.status, info.platform}); return true; }); From 41abe7bf171e4e1632117a554ff9adc309084946 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 10:23:39 +0000 Subject: [PATCH 16/25] Fix clang 12 build --- include/ccf/pal/report_data.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/ccf/pal/report_data.h b/include/ccf/pal/report_data.h index 476a3882ee96..4921d9caffdd 100644 --- a/include/ccf/pal/report_data.h +++ b/include/ccf/pal/report_data.h @@ -53,8 +53,9 @@ namespace ccf::pal crypto::Sha256Hash to_sha256_hash() const { - return crypto::Sha256Hash::from_span( - {data.data(), crypto::Sha256Hash::SIZE}); + std::span s( + data.data(), crypto::Sha256Hash::SIZE); + return crypto::Sha256Hash::from_span(s); } }; From acc3eecd657e07ba34f0d6243e1ee886f47663a9 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 10:42:20 +0000 Subject: [PATCH 17/25] Fix virtual startup --- doc/schemas/gov_openapi.json | 75 ++++++++++++++++++++++------------ include/ccf/pal/attestation.h | 5 ++- src/node/rpc/member_frontend.h | 2 +- src/service/genesis_gen.h | 3 +- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index b559db38dfbb..149b14fdf288 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -63,29 +63,6 @@ }, "type": "object" }, - "CodeDigest": { - "format": "hex", - "pattern": "^[a-f0-9]+$", - "type": "string" - }, - "CodeDigest_to_CodeStatus": { - "items": { - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CodeDigest" - }, - { - "$ref": "#/components/schemas/CodeStatus" - } - ] - }, - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - "type": "array" - }, "CodeStatus": { "enum": [ "AllowedToJoin" @@ -951,6 +928,29 @@ ], "type": "string" }, + "SgxAttestationMeasurement": { + "format": "hex", + "pattern": "^[a-f0-9]64$", + "type": "string" + }, + "SgxAttestationMeasurement_to_CodeStatus": { + "items": { + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SgxAttestationMeasurement" + }, + { + "$ref": "#/components/schemas/CodeStatus" + } + ] + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "type": "array" + }, "Sha256Digest": { "format": "hex", "pattern": "^[a-f0-9]{32}$", @@ -1001,6 +1001,29 @@ ], "type": "object" }, + "SnpAttestationMeasurement": { + "format": "hex", + "pattern": "^[a-f0-9]96$", + "type": "string" + }, + "SnpAttestationMeasurement_to_CodeStatus": { + "items": { + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SnpAttestationMeasurement" + }, + { + "$ref": "#/components/schemas/CodeStatus" + } + ] + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "type": "array" + }, "StateDigest": { "properties": { "state_digest": { @@ -1182,7 +1205,7 @@ "info": { "description": "This API is used to submit and query proposals which affect CCF's public governance tables.", "title": "CCF Governance API", - "version": "2.22.0" + "version": "2.23.0" }, "openapi": "3.0.0", "paths": { @@ -1725,7 +1748,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CodeDigest_to_CodeStatus" + "$ref": "#/components/schemas/SgxAttestationMeasurement_to_CodeStatus" } } }, @@ -1813,7 +1836,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CodeDigest_to_CodeStatus" + "$ref": "#/components/schemas/SnpAttestationMeasurement_to_CodeStatus" } } }, diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 46fbd6dc327c..27e4fa225f78 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -281,8 +281,9 @@ namespace ccf::pal throw std::logic_error( "Cannot verify virtual attestation report if node is SEV-SNP"); } - unique_id = {}; - report_data = {}; + // For now, virtual resembles SGX (mostly for historical reasons) + unique_id = SgxAttestationMeasurement(); + report_data = SgxAttestationReportData(); } else if (quote_info.format == QuoteFormat::amd_sev_snp_v1) { diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index 4954d6faa4bb..db826484184a 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -581,7 +581,7 @@ namespace ccf openapi_info.description = "This API is used to submit and query proposals which affect CCF's " "public governance tables."; - openapi_info.document_version = "2.22.0"; + openapi_info.document_version = "2.23.0"; } static std::optional get_caller_member_id( diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 93ec2cd07a16..1e2122c17e8a 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -419,7 +419,8 @@ namespace ccf { switch (platform) { - // For now, record null code id for virtual platform in code id table + // For now, record null code id for virtual platform in SGX code id + // table case QuoteFormat::insecure_virtual: case QuoteFormat::oe_sgx_v1: { From c8be21457eb983416ca4af70f7343a5a8ce09882 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 10:56:09 +0000 Subject: [PATCH 18/25] First rename pass --- include/ccf/node/quote.h | 5 +++-- include/ccf/pal/attestation.h | 22 +++++++++---------- include/ccf/service/code_digest.h | 14 ++++++------ include/ccf/service/tables/code_id.h | 2 +- src/apps/external_executor/executor_code_id.h | 2 +- .../external_executor/external_executor.cpp | 4 ++-- src/node/node_state.h | 8 +++---- src/node/quote.cpp | 18 +++++++-------- src/node/rpc/node_call_types.h | 2 +- src/node/rpc/node_frontend.h | 10 ++++----- src/node/rpc/node_interface.h | 2 +- src/node/rpc/node_operation.h | 4 ++-- src/node/rpc/node_operation_interface.h | 2 +- src/node/rpc/serialization.h | 2 +- src/node/rpc/test/node_stub.h | 2 +- src/node/uvm_endorsements.h | 2 +- src/service/genesis_gen.h | 7 +++--- 17 files changed, 55 insertions(+), 53 deletions(-) diff --git a/include/ccf/node/quote.h b/include/ccf/node/quote.h index b0fb93d288d9..ce4428f8ee03 100644 --- a/include/ccf/node/quote.h +++ b/include/ccf/node/quote.h @@ -30,7 +30,8 @@ namespace ccf /// In SGX case, extracts the MRENCLAVE from an OE quote. This fails on /// quotes with expired collateral, so it is recommended to cache code IDs /// once they have been successfully extracted. - static std::optional get_code_id(const QuoteInfo& quote_info); + static std::optional get_code_id( + const QuoteInfo& quote_info); // TODO: Rename static std::optional get_host_data(const QuoteInfo& quote_info); @@ -38,7 +39,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest); + PlatformAttestationMeasurement& measurement); }; using EnclaveAttestationProvider CCF_DEPRECATED("Will be removed in 4.x") = diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index 27e4fa225f78..c8d522609942 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -34,7 +34,7 @@ namespace ccf::pal // SGX, this does not require external dependencies (Open Enclave for SGX). static void verify_snp_attestation_report( const QuoteInfo& quote_info, - ccf::CodeDigest& unique_id, + ccf::PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { if (quote_info.format != QuoteFormat::amd_sev_snp_v1) @@ -77,7 +77,7 @@ namespace ccf::pal } report_data = SnpAttestationReportData(quote.report_data); - unique_id = SnpAttestationMeasurement(quote.measurement); + measurement = SnpAttestationMeasurement(quote.measurement); auto certificates = crypto::split_x509_cert_bundle(std::string_view( reinterpret_cast(quote_info.endorsements.data()), @@ -269,7 +269,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - ccf::CodeDigest& unique_id, + ccf::PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { auto is_sev_snp = access(snp::DEVICE, F_OK) == 0; @@ -282,7 +282,7 @@ namespace ccf::pal "Cannot verify virtual attestation report if node is SEV-SNP"); } // For now, virtual resembles SGX (mostly for historical reasons) - unique_id = SgxAttestationMeasurement(); + measurement = SgxAttestationMeasurement(); report_data = SgxAttestationReportData(); } else if (quote_info.format == QuoteFormat::amd_sev_snp_v1) @@ -293,7 +293,7 @@ namespace ccf::pal "Cannot verify SEV-SNP attestation report if node is virtual"); } - verify_snp_attestation_report(quote_info, unique_id, report_data); + verify_snp_attestation_report(quote_info, measurement, report_data); } else { @@ -373,7 +373,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - ccf::CodeDigest& unique_id, + ccf::PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { if (quote_info.format == QuoteFormat::insecure_virtual) @@ -383,7 +383,7 @@ namespace ccf::pal } else if (quote_info.format == QuoteFormat::amd_sev_snp_v1) { - verify_snp_attestation_report(quote_info, unique_id, report_data); + verify_snp_attestation_report(quote_info, measurement, report_data); return; } @@ -406,7 +406,7 @@ namespace ccf::pal oe_result_str(rc))); } - std::optional measurement = std::nullopt; + std::optional claim_measurement = std::nullopt; std::optional custom_claim_report_data = std::nullopt; for (size_t i = 0; i < claims.length; i++) @@ -421,7 +421,7 @@ namespace ccf::pal fmt::format("SGX unique ID claim is not of expected size")); } - measurement = + claim_measurement = SgxAttestationMeasurement({claim.value, claim.value_size}); } else if (claim_name == OE_CLAIM_CUSTOM_CLAIMS_BUFFER) @@ -463,7 +463,7 @@ namespace ccf::pal } } - if (!measurement.has_value()) + if (!claim_measurement.has_value()) { throw std::logic_error( "Could not find measurement in SGX attestation report"); @@ -475,7 +475,7 @@ namespace ccf::pal "Could not find report data in SGX attestation report"); } - unique_id = measurement.value(); + measurement = claim_measurement.value(); report_data = custom_claim_report_data.value(); } diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h index 3b005c4ff7c5..b155d2950bd2 100644 --- a/include/ccf/service/code_digest.h +++ b/include/ccf/service/code_digest.h @@ -10,19 +10,19 @@ namespace ccf { // Generic wrapper for code digests on all TEE platforms // TODO: Rename and make private? - struct CodeDigest + struct PlatformAttestationMeasurement { std::vector data; - CodeDigest() = default; - CodeDigest(const CodeDigest&) = default; + PlatformAttestationMeasurement() = default; + PlatformAttestationMeasurement(const PlatformAttestationMeasurement&) = default; template - CodeDigest(const pal::AttestationMeasurement& measurement) : + PlatformAttestationMeasurement(const pal::AttestationMeasurement& measurement) : data(measurement.measurement.begin(), measurement.measurement.end()) {} - CodeDigest& operator=(const CodeDigest&) = default; + PlatformAttestationMeasurement& operator=(const PlatformAttestationMeasurement&) = default; std::string hex_str() const { @@ -34,8 +34,8 @@ namespace ccf return data; } }; - DECLARE_JSON_TYPE(CodeDigest); - DECLARE_JSON_REQUIRED_FIELDS(CodeDigest, data); + DECLARE_JSON_TYPE(PlatformAttestationMeasurement); + DECLARE_JSON_REQUIRED_FIELDS(PlatformAttestationMeasurement, data); enum class CodeStatus { diff --git a/include/ccf/service/tables/code_id.h b/include/ccf/service/tables/code_id.h index d1ab94c8bcb6..87c35fc8fc97 100644 --- a/include/ccf/service/tables/code_id.h +++ b/include/ccf/service/tables/code_id.h @@ -2,7 +2,7 @@ // Licensed under the Apache 2.0 License. #pragma once -#include "ccf/pal/attestation_sgx.h" +#include "ccf/pal/measurement.h" #include "ccf/service/code_digest.h" #include "ccf/service/map.h" diff --git a/src/apps/external_executor/executor_code_id.h b/src/apps/external_executor/executor_code_id.h index 94fa0ca1963a..9275891a1ff5 100644 --- a/src/apps/external_executor/executor_code_id.h +++ b/src/apps/external_executor/executor_code_id.h @@ -18,7 +18,7 @@ namespace externalexecutor kv::ReadOnlyTx& tx, const externalexecutor::protobuf::Attestation& quote_info, const std::string& expected_node_public_key_der, - ccf::CodeDigest& code_digest) + ccf::PlatformAttestationMeasurement& measurement) { return ccf::QuoteVerificationResult::Verified; } diff --git a/src/apps/external_executor/external_executor.cpp b/src/apps/external_executor/external_executor.cpp index 565f50139a08..126b9a53b101 100644 --- a/src/apps/external_executor/external_executor.cpp +++ b/src/apps/external_executor/external_executor.cpp @@ -331,9 +331,9 @@ namespace externalexecutor -> ccf::grpc::GrpcAdapterResponse< externalexecutor::protobuf::RegistrationResult> { // verify quote - ccf::CodeDigest code_digest; + ccf::PlatformAttestationMeasurement measurement; ccf::QuoteVerificationResult verify_result = verify_executor_quote( - ctx.tx, payload.attestation(), payload.cert(), code_digest); + ctx.tx, payload.attestation(), payload.cert(), measurement); if (verify_result != ccf::QuoteVerificationResult::Verified) { diff --git a/src/node/node_state.h b/src/node/node_state.h index 24f61587423a..301ad303d699 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -90,7 +90,7 @@ namespace ccf crypto::Pem self_signed_node_cert; std::optional endorsed_node_cert = std::nullopt; QuoteInfo quote_info; - CodeDigest node_measurement; + PlatformAttestationMeasurement node_measurement; StartupConfig config; std::optional snp_uvm_endorsements = std::nullopt; std::vector startup_snapshot; @@ -241,10 +241,10 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) override + PlatformAttestationMeasurement& measurement) override { return AttestationProvider::verify_quote_against_store( - tx, quote_info, expected_node_public_key_der, code_digest); + tx, quote_info, expected_node_public_key_der, measurement); } // @@ -1920,7 +1920,7 @@ namespace ccf create_params.service_cert = network.identity->cert; create_params.quote_info = quote_info; create_params.public_encryption_key = node_encrypt_kp->public_key_pem(); - create_params.code_digest = node_measurement; + create_params.measurement = node_measurement; create_params.snp_uvm_endorsements = snp_uvm_endorsements; create_params.snp_security_policy = config.attestation.environment.security_policy; diff --git a/src/node/quote.cpp b/src/node/quote.cpp index e9e6f66bfbfb..beef7e30b198 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -13,7 +13,7 @@ namespace ccf { bool verify_enclave_measurement_against_uvm_endorsements( kv::ReadOnlyTx& tx, - const CodeDigest& quote_measurement, + const PlatformAttestationMeasurement& quote_measurement, const std::vector& uvm_endorsements) { auto uvm_endorsements_data = @@ -47,7 +47,7 @@ namespace ccf QuoteVerificationResult verify_enclave_measurement_against_store( kv::ReadOnlyTx& tx, - const CodeDigest& quote_measurement, + const PlatformAttestationMeasurement& quote_measurement, const QuoteFormat& quote_format, const std::optional>& uvm_endorsements = std::nullopt) { @@ -109,10 +109,10 @@ namespace ccf return QuoteVerificationResult::Verified; } - std::optional AttestationProvider::get_code_id( - const QuoteInfo& quote_info) + std::optional AttestationProvider:: + get_code_id(const QuoteInfo& quote_info) { - CodeDigest measurement = {}; + PlatformAttestationMeasurement measurement = {}; pal::PlatformAttestationReportData r = {}; try { @@ -137,7 +137,7 @@ namespace ccf HostData digest{}; HostData::Representation rep{}; - CodeDigest d = {}; + PlatformAttestationMeasurement d = {}; pal::PlatformAttestationReportData r = {}; try { @@ -185,13 +185,13 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) + PlatformAttestationMeasurement& measurement) { crypto::Sha256Hash quoted_hash; pal::PlatformAttestationReportData report_data; try { - pal::verify_quote(quote_info, code_digest, report_data); + pal::verify_quote(quote_info, measurement, report_data); quoted_hash = report_data.to_sha256_hash(); } catch (const std::exception& e) @@ -215,7 +215,7 @@ namespace ccf } auto rc = verify_enclave_measurement_against_store( - tx, code_digest, quote_info.format, quote_info.uvm_endorsements); + tx, measurement, quote_info.format, quote_info.uvm_endorsements); if (rc != QuoteVerificationResult::Verified) { return rc; diff --git a/src/node/rpc/node_call_types.h b/src/node/rpc/node_call_types.h index fd7c36e49a8d..ea030eaf1dc8 100644 --- a/src/node/rpc/node_call_types.h +++ b/src/node/rpc/node_call_types.h @@ -60,7 +60,7 @@ namespace ccf crypto::Pem service_cert; QuoteInfo quote_info; crypto::Pem public_encryption_key; - CodeDigest code_digest; + PlatformAttestationMeasurement measurement; std::optional snp_security_policy = std::nullopt; // base64-encoded std::optional snp_uvm_endorsements = std::nullopt; diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index 9ae4eadc28ae..96d2ed71a3d0 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -280,10 +280,10 @@ namespace ccf auto pubk_der = crypto::public_key_der_from_cert(node_der); NodeId joining_node_id = compute_node_id_from_pubk_der(pubk_der); - CodeDigest code_digest; + PlatformAttestationMeasurement measurement; QuoteVerificationResult verify_result = this->node_operation.verify_quote( - tx, in.quote_info, pubk_der, code_digest); + tx, in.quote_info, pubk_der, measurement); if (verify_result != QuoteVerificationResult::Verified) { const auto [code, message] = quote_verification_error(verify_result); @@ -321,7 +321,7 @@ namespace ccf in.public_encryption_key, node_status, ledger_secret_seqno, - ds::to_hex(code_digest.data), + measurement.hex_str(), in.certificate_signing_request, client_public_key_pem, in.node_data}; @@ -1548,7 +1548,7 @@ namespace ccf in.public_encryption_key, NodeStatus::TRUSTED, std::nullopt, - in.code_digest.hex_str(), + in.measurement.hex_str(), in.certificate_signing_request, in.public_key, in.node_data}; @@ -1559,7 +1559,7 @@ namespace ccf { // For improved serviceability on SNP, do not record trusted // measurements if UVM endorsements are available - g.trust_node_measurement(in.code_digest, in.quote_info.format); + g.trust_node_measurement(in.measurement, in.quote_info.format); } if (in.quote_info.format == QuoteFormat::amd_sev_snp_v1) { diff --git a/src/node/rpc/node_interface.h b/src/node/rpc/node_interface.h index bbedfd92cf6e..6b535e12995d 100644 --- a/src/node/rpc/node_interface.h +++ b/src/node/rpc/node_interface.h @@ -51,7 +51,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) = 0; + PlatformAttestationMeasurement& measurement) = 0; virtual kv::Version get_startup_snapshot_seqno() = 0; virtual SessionMetrics get_session_metrics() = 0; virtual size_t get_jwt_attempts() = 0; diff --git a/src/node/rpc/node_operation.h b/src/node/rpc/node_operation.h index 82b0a49efd47..4eb5a16c3b27 100644 --- a/src/node/rpc/node_operation.h +++ b/src/node/rpc/node_operation.h @@ -74,10 +74,10 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) override + PlatformAttestationMeasurement& measurement) override { return impl.verify_quote( - tx, quote_info, expected_node_public_key_der, code_digest); + tx, quote_info, expected_node_public_key_der, measurement); } void initiate_private_recovery(kv::Tx& tx) override diff --git a/src/node/rpc/node_operation_interface.h b/src/node/rpc/node_operation_interface.h index 8d6b3eee4825..66d02263a434 100644 --- a/src/node/rpc/node_operation_interface.h +++ b/src/node/rpc/node_operation_interface.h @@ -48,7 +48,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) = 0; + PlatformAttestationMeasurement& measurement) = 0; virtual void initiate_private_recovery(kv::Tx& tx) = 0; diff --git a/src/node/rpc/serialization.h b/src/node/rpc/serialization.h index 2d356f69b84e..16d229bda551 100644 --- a/src/node/rpc/serialization.h +++ b/src/node/rpc/serialization.h @@ -71,7 +71,7 @@ namespace ccf service_cert, quote_info, public_encryption_key, - code_digest, + measurement, node_info_network, create_txid) DECLARE_JSON_OPTIONAL_FIELDS( diff --git a/src/node/rpc/test/node_stub.h b/src/node/rpc/test/node_stub.h index f9c87aa581b8..dca30db5c292 100644 --- a/src/node/rpc/test/node_stub.h +++ b/src/node/rpc/test/node_stub.h @@ -71,7 +71,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - CodeDigest& code_digest) override + PlatformAttestationMeasurement& measurement) override { return QuoteVerificationResult::Verified; } diff --git a/src/node/uvm_endorsements.h b/src/node/uvm_endorsements.h index b123899e7533..544d3344479c 100644 --- a/src/node/uvm_endorsements.h +++ b/src/node/uvm_endorsements.h @@ -236,7 +236,7 @@ namespace ccf static UVMEndorsements verify_uvm_endorsements( const std::vector& uvm_endorsements_raw, - const CodeDigest& uvm_measurement) + const PlatformAttestationMeasurement& uvm_measurement) { auto phdr = cose::decode_protected_header(uvm_endorsements_raw); diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 1e2122c17e8a..0843593ef4d8 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -415,7 +415,8 @@ namespace ccf } void trust_node_measurement( - const CodeDigest& node_code_id, const QuoteFormat& platform) + const PlatformAttestationMeasurement& node_measurement, + const QuoteFormat& platform) { switch (platform) { @@ -426,7 +427,7 @@ namespace ccf { tx.rw(Tables::NODE_CODE_IDS) ->put( - pal::SgxAttestationMeasurement(node_code_id), + pal::SgxAttestationMeasurement(node_measurement), CodeStatus::ALLOWED_TO_JOIN); break; } @@ -434,7 +435,7 @@ namespace ccf { tx.rw(Tables::NODE_SNP_MEASUREMENTS) ->put( - pal::SnpAttestationMeasurement(node_code_id), + pal::SnpAttestationMeasurement(node_measurement), CodeStatus::ALLOWED_TO_JOIN); break; } From 61dd7529154e5a8324f59ba9d03d41924394a0ba Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 11:04:25 +0000 Subject: [PATCH 19/25] More renames --- include/ccf/node/quote.h | 4 ++-- src/node/node_state.h | 6 +++--- src/node/quote.cpp | 2 +- src/node/rpc/node_frontend.h | 31 ++++++++++++++++--------------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/include/ccf/node/quote.h b/include/ccf/node/quote.h index ce4428f8ee03..932aabeed376 100644 --- a/include/ccf/node/quote.h +++ b/include/ccf/node/quote.h @@ -30,8 +30,8 @@ namespace ccf /// In SGX case, extracts the MRENCLAVE from an OE quote. This fails on /// quotes with expired collateral, so it is recommended to cache code IDs /// once they have been successfully extracted. - static std::optional get_code_id( - const QuoteInfo& quote_info); // TODO: Rename + static std::optional get_measurement( + const QuoteInfo& quote_info); static std::optional get_host_data(const QuoteInfo& quote_info); diff --git a/src/node/node_state.h b/src/node/node_state.h index 301ad303d699..390ffb46905d 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -286,10 +286,10 @@ namespace ccf // void launch_node() { - auto code_id = AttestationProvider::get_code_id(quote_info); - if (code_id.has_value()) + auto measurement = AttestationProvider::get_measurement(quote_info); + if (measurement.has_value()) { - node_measurement = code_id.value(); + node_measurement = measurement.value(); } else { diff --git a/src/node/quote.cpp b/src/node/quote.cpp index beef7e30b198..e0d4928915ec 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -110,7 +110,7 @@ namespace ccf } std::optional AttestationProvider:: - get_code_id(const QuoteInfo& quote_info) + get_measurement(const QuoteInfo& quote_info) { PlatformAttestationMeasurement measurement = {}; pal::PlatformAttestationReportData r = {}; diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index 96d2ed71a3d0..b1aff9d17b48 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -720,12 +720,12 @@ namespace ccf q.format = node_quote_info.format; q.uvm_endorsements = node_quote_info.uvm_endorsements; - // get_code_id attempts to re-validate the quote to extract mrenclave - // and the Open Enclave is insufficiently flexible to allow quotes - // with expired collateral to be parsed at all. Recent nodes therefore - // cache their code digest on startup, and this code attempts to fetch - // that value when possible and only call the unreliable get_code_id - // otherwise. + // get_measurement attempts to re-validate the quote to extract + // mrenclave and the Open Enclave is insufficiently flexible to allow + // quotes with expired collateral to be parsed at all. Recent nodes + // therefore cache their code digest on startup, and this code + // attempts to fetch that value when possible and only call the + // unreliable get_measurement otherwise. auto nodes = args.tx.ro(network.nodes); auto node_info = nodes->get(context.get_node_id()); if (node_info.has_value() && node_info->code_digest.has_value()) @@ -734,10 +734,11 @@ namespace ccf } else { - auto code_id = AttestationProvider::get_code_id(node_quote_info); - if (code_id.has_value()) + auto measurement = + AttestationProvider::get_measurement(node_quote_info); + if (measurement.has_value()) { - q.mrenclave = ds::to_hex(code_id.value().data); + q.mrenclave = measurement.value().hex_str(); } else { @@ -790,23 +791,23 @@ namespace ccf q.endorsements = node_info.quote_info.endorsements; q.format = node_info.quote_info.format; - // get_code_id attempts to re-validate the quote to extract + // get_measurement attempts to re-validate the quote to extract // mrenclave and the Open Enclave is insufficiently flexible to // allow quotes with expired collateral to be parsed at all. Recent // nodes therefore cache their code digest on startup, and this code // attempts to fetch that value when possible and only call the - // unreliable get_code_id otherwise. + // unreliable get_measurement otherwise. if (node_info.code_digest.has_value()) { q.mrenclave = node_info.code_digest.value(); } else { - auto code_id = - AttestationProvider::get_code_id(node_info.quote_info); - if (code_id.has_value()) + auto measurement = + AttestationProvider::get_measurement(node_info.quote_info); + if (measurement.has_value()) { - q.mrenclave = ds::to_hex(code_id.value().data); + q.mrenclave = measurement.value().hex_str(); } } quotes.emplace_back(q); From 52535f2f183269cab71e4485556fac14d5a12b1d Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 11:37:12 +0000 Subject: [PATCH 20/25] Final renames --- include/ccf/node/quote.h | 6 +-- include/ccf/pal/attestation.h | 8 ++-- include/ccf/pal/measurement.h | 31 +++++++++++++ include/ccf/pal/report_data.h | 22 ++++----- include/ccf/service/code_digest.h | 46 ------------------- include/ccf/service/code_status.h | 17 +++++++ include/ccf/service/tables/code_id.h | 2 +- include/ccf/service/tables/snp_measurements.h | 1 + src/apps/external_executor/executor_code_id.h | 4 +- .../external_executor/external_executor.cpp | 2 +- src/node/node_state.h | 4 +- src/node/quote.cpp | 12 ++--- src/node/rpc/node_call_types.h | 2 +- src/node/rpc/node_frontend.h | 2 +- src/node/rpc/node_interface.h | 2 +- src/node/rpc/node_operation.h | 2 +- src/node/rpc/node_operation_interface.h | 2 +- src/node/rpc/test/node_stub.h | 2 +- src/node/uvm_endorsements.h | 2 +- src/service/genesis_gen.h | 2 +- 20 files changed, 87 insertions(+), 84 deletions(-) delete mode 100644 include/ccf/service/code_digest.h create mode 100644 include/ccf/service/code_status.h diff --git a/include/ccf/node/quote.h b/include/ccf/node/quote.h index 932aabeed376..99e40684bb6e 100644 --- a/include/ccf/node/quote.h +++ b/include/ccf/node/quote.h @@ -4,7 +4,7 @@ #include "ccf/ccf_deprecated.h" #include "ccf/ds/quote_info.h" -#include "ccf/service/code_digest.h" +#include "ccf/pal/measurement.h" #include "ccf/service/tables/host_data.h" #include "ccf/tx.h" @@ -30,7 +30,7 @@ namespace ccf /// In SGX case, extracts the MRENCLAVE from an OE quote. This fails on /// quotes with expired collateral, so it is recommended to cache code IDs /// once they have been successfully extracted. - static std::optional get_measurement( + static std::optional get_measurement( const QuoteInfo& quote_info); static std::optional get_host_data(const QuoteInfo& quote_info); @@ -39,7 +39,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement); + pal::PlatformAttestationMeasurement& measurement); }; using EnclaveAttestationProvider CCF_DEPRECATED("Will be removed in 4.x") = diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index c8d522609942..a833bc7aa416 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -9,7 +9,7 @@ #include "ccf/ds/logger.h" #include "ccf/ds/quote_info.h" #include "ccf/pal/attestation_sev_snp.h" -#include "ccf/service/code_digest.h" +#include "ccf/pal/measurement.h" #include #include @@ -34,7 +34,7 @@ namespace ccf::pal // SGX, this does not require external dependencies (Open Enclave for SGX). static void verify_snp_attestation_report( const QuoteInfo& quote_info, - ccf::PlatformAttestationMeasurement& measurement, + PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { if (quote_info.format != QuoteFormat::amd_sev_snp_v1) @@ -269,7 +269,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - ccf::PlatformAttestationMeasurement& measurement, + PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { auto is_sev_snp = access(snp::DEVICE, F_OK) == 0; @@ -373,7 +373,7 @@ namespace ccf::pal static void verify_quote( const QuoteInfo& quote_info, - ccf::PlatformAttestationMeasurement& measurement, + PlatformAttestationMeasurement& measurement, PlatformAttestationReportData& report_data) { if (quote_info.format == QuoteFormat::insecure_virtual) diff --git a/include/ccf/pal/measurement.h b/include/ccf/pal/measurement.h index e91babf17250..c6822f919c2a 100644 --- a/include/ccf/pal/measurement.h +++ b/include/ccf/pal/measurement.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/ds/hex.h" +#include "ccf/ds/json.h" #include "ccf/kv/serialisers/blit_serialiser.h" #include @@ -110,6 +111,36 @@ namespace ccf::pal return "SnpAttestationMeasurement"; } + // Generic wrapper for code digests on all TEE platforms + struct PlatformAttestationMeasurement + { + std::vector data; + + PlatformAttestationMeasurement() = default; + PlatformAttestationMeasurement(const PlatformAttestationMeasurement&) = + default; + + template + PlatformAttestationMeasurement( + const AttestationMeasurement& measurement) : + data(measurement.measurement.begin(), measurement.measurement.end()) + {} + + PlatformAttestationMeasurement& operator=( + const PlatformAttestationMeasurement&) = default; + + std::string hex_str() const + { + return ds::to_hex(data); + } + + operator std::span() const + { + return data; + } + }; + DECLARE_JSON_TYPE(PlatformAttestationMeasurement); + DECLARE_JSON_REQUIRED_FIELDS(PlatformAttestationMeasurement, data); } namespace kv::serialisers diff --git a/include/ccf/pal/report_data.h b/include/ccf/pal/report_data.h index 4921d9caffdd..8b1218e59834 100644 --- a/include/ccf/pal/report_data.h +++ b/include/ccf/pal/report_data.h @@ -36,6 +36,17 @@ namespace ccf::pal } }; + // SGX + static constexpr size_t sgx_attestation_report_data_size = 32; + using SgxAttestationReportData = + AttestationReportData; + + // SNP + static constexpr size_t snp_attestation_report_data_size = 64; + using SnpAttestationReportData = + AttestationReportData; + + // Generic wrapper for attestation report data for _all_ platforms. struct PlatformAttestationReportData { std::vector data; @@ -58,15 +69,4 @@ namespace ccf::pal return crypto::Sha256Hash::from_span(s); } }; - - // SGX - static constexpr size_t sgx_attestation_report_data_size = 32; - using SgxAttestationReportData = - AttestationReportData; - - // SNP - static constexpr size_t snp_attestation_report_data_size = 64; - using SnpAttestationReportData = - AttestationReportData; - } \ No newline at end of file diff --git a/include/ccf/service/code_digest.h b/include/ccf/service/code_digest.h deleted file mode 100644 index b155d2950bd2..000000000000 --- a/include/ccf/service/code_digest.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the Apache 2.0 License. -#pragma once - -#include "ccf/ds/hex.h" -#include "ccf/ds/json.h" -#include "ccf/pal/measurement.h" - -namespace ccf -{ - // Generic wrapper for code digests on all TEE platforms - // TODO: Rename and make private? - struct PlatformAttestationMeasurement - { - std::vector data; - - PlatformAttestationMeasurement() = default; - PlatformAttestationMeasurement(const PlatformAttestationMeasurement&) = default; - - template - PlatformAttestationMeasurement(const pal::AttestationMeasurement& measurement) : - data(measurement.measurement.begin(), measurement.measurement.end()) - {} - - PlatformAttestationMeasurement& operator=(const PlatformAttestationMeasurement&) = default; - - std::string hex_str() const - { - return ds::to_hex(data); - } - - operator std::span() const - { - return data; - } - }; - DECLARE_JSON_TYPE(PlatformAttestationMeasurement); - DECLARE_JSON_REQUIRED_FIELDS(PlatformAttestationMeasurement, data); - - enum class CodeStatus - { - ALLOWED_TO_JOIN = 0 - }; - DECLARE_JSON_ENUM( - CodeStatus, {{CodeStatus::ALLOWED_TO_JOIN, "AllowedToJoin"}}); -} \ No newline at end of file diff --git a/include/ccf/service/code_status.h b/include/ccf/service/code_status.h new file mode 100644 index 000000000000..3ff84a6e83d3 --- /dev/null +++ b/include/ccf/service/code_status.h @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#pragma once + +#include "ccf/ds/hex.h" +#include "ccf/ds/json.h" +#include "ccf/pal/measurement.h" + +namespace ccf +{ + enum class CodeStatus + { + ALLOWED_TO_JOIN = 0 + }; + DECLARE_JSON_ENUM( + CodeStatus, {{CodeStatus::ALLOWED_TO_JOIN, "AllowedToJoin"}}); +} \ No newline at end of file diff --git a/include/ccf/service/tables/code_id.h b/include/ccf/service/tables/code_id.h index 87c35fc8fc97..03a76ac8c590 100644 --- a/include/ccf/service/tables/code_id.h +++ b/include/ccf/service/tables/code_id.h @@ -3,7 +3,7 @@ #pragma once #include "ccf/pal/measurement.h" -#include "ccf/service/code_digest.h" +#include "ccf/service/code_status.h" #include "ccf/service/map.h" namespace ccf diff --git a/include/ccf/service/tables/snp_measurements.h b/include/ccf/service/tables/snp_measurements.h index 5db722bc87fd..c212839c111b 100644 --- a/include/ccf/service/tables/snp_measurements.h +++ b/include/ccf/service/tables/snp_measurements.h @@ -3,6 +3,7 @@ #pragma once #include "ccf/pal/measurement.h" +#include "ccf/service/code_status.h" #include "ccf/service/map.h" namespace ccf diff --git a/src/apps/external_executor/executor_code_id.h b/src/apps/external_executor/executor_code_id.h index 9275891a1ff5..75148e5b2fe7 100644 --- a/src/apps/external_executor/executor_code_id.h +++ b/src/apps/external_executor/executor_code_id.h @@ -5,7 +5,7 @@ #include "ccf/ds/json.h" #include "ccf/node/quote.h" #include "ccf/pal/attestation_sev_snp.h" -#include "ccf/service/code_digest.h" +#include "ccf/pal/measurement.h" #include "ccf/service/map.h" #include "ccf/service/tables/code_id.h" #include "endpoints/grpc/status.h" @@ -18,7 +18,7 @@ namespace externalexecutor kv::ReadOnlyTx& tx, const externalexecutor::protobuf::Attestation& quote_info, const std::string& expected_node_public_key_der, - ccf::PlatformAttestationMeasurement& measurement) + ccf::pal::PlatformAttestationMeasurement& measurement) { return ccf::QuoteVerificationResult::Verified; } diff --git a/src/apps/external_executor/external_executor.cpp b/src/apps/external_executor/external_executor.cpp index 126b9a53b101..3fd55b9e8b12 100644 --- a/src/apps/external_executor/external_executor.cpp +++ b/src/apps/external_executor/external_executor.cpp @@ -331,7 +331,7 @@ namespace externalexecutor -> ccf::grpc::GrpcAdapterResponse< externalexecutor::protobuf::RegistrationResult> { // verify quote - ccf::PlatformAttestationMeasurement measurement; + ccf::pal::PlatformAttestationMeasurement measurement; ccf::QuoteVerificationResult verify_result = verify_executor_quote( ctx.tx, payload.attestation(), payload.cert(), measurement); diff --git a/src/node/node_state.h b/src/node/node_state.h index 390ffb46905d..5458316a8656 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -90,7 +90,7 @@ namespace ccf crypto::Pem self_signed_node_cert; std::optional endorsed_node_cert = std::nullopt; QuoteInfo quote_info; - PlatformAttestationMeasurement node_measurement; + pal::PlatformAttestationMeasurement node_measurement; StartupConfig config; std::optional snp_uvm_endorsements = std::nullopt; std::vector startup_snapshot; @@ -241,7 +241,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) override + pal::PlatformAttestationMeasurement& measurement) override { return AttestationProvider::verify_quote_against_store( tx, quote_info, expected_node_public_key_der, measurement); diff --git a/src/node/quote.cpp b/src/node/quote.cpp index e0d4928915ec..9396013bebc4 100644 --- a/src/node/quote.cpp +++ b/src/node/quote.cpp @@ -13,7 +13,7 @@ namespace ccf { bool verify_enclave_measurement_against_uvm_endorsements( kv::ReadOnlyTx& tx, - const PlatformAttestationMeasurement& quote_measurement, + const pal::PlatformAttestationMeasurement& quote_measurement, const std::vector& uvm_endorsements) { auto uvm_endorsements_data = @@ -47,7 +47,7 @@ namespace ccf QuoteVerificationResult verify_enclave_measurement_against_store( kv::ReadOnlyTx& tx, - const PlatformAttestationMeasurement& quote_measurement, + const pal::PlatformAttestationMeasurement& quote_measurement, const QuoteFormat& quote_format, const std::optional>& uvm_endorsements = std::nullopt) { @@ -109,10 +109,10 @@ namespace ccf return QuoteVerificationResult::Verified; } - std::optional AttestationProvider:: + std::optional AttestationProvider:: get_measurement(const QuoteInfo& quote_info) { - PlatformAttestationMeasurement measurement = {}; + pal::PlatformAttestationMeasurement measurement = {}; pal::PlatformAttestationReportData r = {}; try { @@ -137,7 +137,7 @@ namespace ccf HostData digest{}; HostData::Representation rep{}; - PlatformAttestationMeasurement d = {}; + pal::PlatformAttestationMeasurement d = {}; pal::PlatformAttestationReportData r = {}; try { @@ -185,7 +185,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) + pal::PlatformAttestationMeasurement& measurement) { crypto::Sha256Hash quoted_hash; pal::PlatformAttestationReportData report_data; diff --git a/src/node/rpc/node_call_types.h b/src/node/rpc/node_call_types.h index ea030eaf1dc8..ad9e1950f16d 100644 --- a/src/node/rpc/node_call_types.h +++ b/src/node/rpc/node_call_types.h @@ -60,7 +60,7 @@ namespace ccf crypto::Pem service_cert; QuoteInfo quote_info; crypto::Pem public_encryption_key; - PlatformAttestationMeasurement measurement; + pal::PlatformAttestationMeasurement measurement; std::optional snp_security_policy = std::nullopt; // base64-encoded std::optional snp_uvm_endorsements = std::nullopt; diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index b1aff9d17b48..5880d06c358c 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -280,7 +280,7 @@ namespace ccf auto pubk_der = crypto::public_key_der_from_cert(node_der); NodeId joining_node_id = compute_node_id_from_pubk_der(pubk_der); - PlatformAttestationMeasurement measurement; + pal::PlatformAttestationMeasurement measurement; QuoteVerificationResult verify_result = this->node_operation.verify_quote( tx, in.quote_info, pubk_der, measurement); diff --git a/src/node/rpc/node_interface.h b/src/node/rpc/node_interface.h index 6b535e12995d..c5a804a8d1c2 100644 --- a/src/node/rpc/node_interface.h +++ b/src/node/rpc/node_interface.h @@ -51,7 +51,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) = 0; + pal::PlatformAttestationMeasurement& measurement) = 0; virtual kv::Version get_startup_snapshot_seqno() = 0; virtual SessionMetrics get_session_metrics() = 0; virtual size_t get_jwt_attempts() = 0; diff --git a/src/node/rpc/node_operation.h b/src/node/rpc/node_operation.h index 4eb5a16c3b27..748f68b49039 100644 --- a/src/node/rpc/node_operation.h +++ b/src/node/rpc/node_operation.h @@ -74,7 +74,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) override + pal::PlatformAttestationMeasurement& measurement) override { return impl.verify_quote( tx, quote_info, expected_node_public_key_der, measurement); diff --git a/src/node/rpc/node_operation_interface.h b/src/node/rpc/node_operation_interface.h index 66d02263a434..b08caea70270 100644 --- a/src/node/rpc/node_operation_interface.h +++ b/src/node/rpc/node_operation_interface.h @@ -48,7 +48,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) = 0; + pal::PlatformAttestationMeasurement& measurement) = 0; virtual void initiate_private_recovery(kv::Tx& tx) = 0; diff --git a/src/node/rpc/test/node_stub.h b/src/node/rpc/test/node_stub.h index dca30db5c292..77f709169cd5 100644 --- a/src/node/rpc/test/node_stub.h +++ b/src/node/rpc/test/node_stub.h @@ -71,7 +71,7 @@ namespace ccf kv::ReadOnlyTx& tx, const QuoteInfo& quote_info, const std::vector& expected_node_public_key_der, - PlatformAttestationMeasurement& measurement) override + pal::PlatformAttestationMeasurement& measurement) override { return QuoteVerificationResult::Verified; } diff --git a/src/node/uvm_endorsements.h b/src/node/uvm_endorsements.h index 544d3344479c..32392a33620e 100644 --- a/src/node/uvm_endorsements.h +++ b/src/node/uvm_endorsements.h @@ -236,7 +236,7 @@ namespace ccf static UVMEndorsements verify_uvm_endorsements( const std::vector& uvm_endorsements_raw, - const PlatformAttestationMeasurement& uvm_measurement) + const pal::PlatformAttestationMeasurement& uvm_measurement) { auto phdr = cose::decode_protected_header(uvm_endorsements_raw); diff --git a/src/service/genesis_gen.h b/src/service/genesis_gen.h index 0843593ef4d8..b302a1d3ae7b 100644 --- a/src/service/genesis_gen.h +++ b/src/service/genesis_gen.h @@ -415,7 +415,7 @@ namespace ccf } void trust_node_measurement( - const PlatformAttestationMeasurement& node_measurement, + const pal::PlatformAttestationMeasurement& node_measurement, const QuoteFormat& platform) { switch (platform) From a64acd6e07f85397d513e647aa6deef34687db84 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 13:14:34 +0000 Subject: [PATCH 21/25] Changelog --- CHANGELOG.md | 1 + include/ccf/pal/attestation.h | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0d141249114..fbaf066f30d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Additional logging of historical query flow in `UNSAFE` builds. - Historical query system will re-request entries if the host fails to provide them within a fixed time. +- Renamed `ccf::CodeDigest` to `ccf:pal::PlatformAttestationMeasurement` and `get_code_id()` to `get_measurement()` (#5063). ### Dependencies diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index a833bc7aa416..f3bc8c4cfc74 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -324,7 +324,6 @@ namespace ccf::pal sgx::Endorsements endorsements; sgx::SerialisedClaims serialised_custom_claims; - // Serialise hash of node's public key as a custom claim const size_t custom_claim_length = 1; oe_claim_t custom_claim; custom_claim.name = const_cast(sgx::report_data_claim_name); @@ -418,7 +417,7 @@ namespace ccf::pal if (claim.value_size != SgxAttestationMeasurement::size()) { throw std::logic_error( - fmt::format("SGX unique ID claim is not of expected size")); + fmt::format("SGX measurement claim is not of expected size")); } claim_measurement = From 617d51f18b0a78d9e53a56f66fe132e4bc244cab Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 13:26:19 +0000 Subject: [PATCH 22/25] Fix code update test virtual --- tests/code_update.py | 2 +- tests/infra/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/code_update.py b/tests/code_update.py index 6375a3d7f709..1ca15243dadd 100644 --- a/tests/code_update.py +++ b/tests/code_update.py @@ -16,7 +16,7 @@ from loguru import logger as LOG # Dummy code id used by virtual nodes -VIRTUAL_CODE_ID = "0" * 96 +VIRTUAL_CODE_ID = "0" * 64 @reqs.description("Verify node evidence") diff --git a/tests/infra/utils.py b/tests/infra/utils.py index 6e023f7ba672..db2b5c58fc96 100644 --- a/tests/infra/utils.py +++ b/tests/infra/utils.py @@ -28,4 +28,4 @@ def get_code_id( return lines[0].split("=")[1] else: # Virtual and SNP - return hashlib.sha384(lib_path.encode()).hexdigest() + return hashlib.sha256(lib_path.encode()).hexdigest() From 66134420c0397a3dac8257a1e4b6b6d6b40dce24 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 13:28:15 +0000 Subject: [PATCH 23/25] Fix SNP build --- include/ccf/pal/attestation.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/ccf/pal/attestation.h b/include/ccf/pal/attestation.h index f3bc8c4cfc74..4f809594336e 100644 --- a/include/ccf/pal/attestation.h +++ b/include/ccf/pal/attestation.h @@ -229,7 +229,9 @@ namespace ccf::pal // Arbitrary report data memcpy( - req.report_data, report_data.data(), snp_attestation_report_data_size); + req.report_data, + report_data.data.data(), + snp_attestation_report_data_size); // Documented at // https://www.kernel.org/doc/html/latest/virt/coco/sev-guest.html From 5e8a72031ecede96645164630ff887c76ab81361 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 13:33:12 +0000 Subject: [PATCH 24/25] . --- src/crypto/sha256_hash.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/crypto/sha256_hash.cpp b/src/crypto/sha256_hash.cpp index c101162ce4d2..10b8125523b8 100644 --- a/src/crypto/sha256_hash.cpp +++ b/src/crypto/sha256_hash.cpp @@ -4,7 +4,6 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/hex.h" -#include "ccf/ds/logger.h" namespace crypto { From 08e29ae01037234fd5d836d5e0f97975967f17cc Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 28 Feb 2023 13:57:01 +0000 Subject: [PATCH 25/25] . --- .daily_canary | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.daily_canary b/.daily_canary index 9ad3cd2975b9..fd07e7d929a7 100644 --- a/.daily_canary +++ b/.daily_canary @@ -1,4 +1,4 @@ ___ ___ - (~ ~) (o o) | Y & + + (- -) (o o) | Y & + ( V ) z O z O +---'---' /--x-m- /--m-m---xXx--/--yy------