Skip to content

Commit

Permalink
Basic table manipulation
Browse files Browse the repository at this point in the history
  • Loading branch information
cjen1-msft committed Feb 21, 2025
1 parent a026daf commit 8b5aefd
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 47 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,11 @@ if(BUILD_TESTS)
${CMAKE_CURRENT_SOURCE_DIR}/src/pal/test/snp_tcb_verification.cpp
)

add_unit_test(
snp_attestation
${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/snp_attestation.cpp
)

add_unit_test(map_test ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/map_test.cpp)

add_unit_test(
Expand Down
7 changes: 7 additions & 0 deletions include/ccf/node/quote.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include "ccf/ccf_deprecated.h"
#include "ccf/ds/quote_info.h"
#include "ccf/pal/measurement.h"
#include "ccf/pal/snp_tcb_version.h"
#include "ccf/service/tables/host_data.h"
#include "ccf/service/tables/tcb_versions.h"
#include "ccf/tx.h"

#include <optional>
Expand Down Expand Up @@ -36,10 +38,15 @@ namespace ccf

static std::optional<HostData> get_host_data(const QuoteInfo& quote_info);

static std::optional<pal::snp::TcbPolicy> get_snp_tcb_quote(const QuoteInfo& quote_info);

static QuoteVerificationResult verify_quote_against_store(
ccf::kv::ReadOnlyTx& tx,
const QuoteInfo& quote_info,
const std::vector<uint8_t>& expected_node_public_key_der,
pal::PlatformAttestationMeasurement& measurement);
};

QuoteVerificationResult verify_tcb_version_against_store(
ccf::kv::ReadOnlyTx& tx, const QuoteInfo& quote_info);
}
13 changes: 13 additions & 0 deletions include/ccf/pal/snp_tcb_version.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <stdint.h>
#include "ccf/ds/json.h"

#pragma once

namespace ccf::pal::snp
{
#pragma pack(push, 1)
Expand All @@ -23,4 +25,15 @@ namespace ccf::pal::snp
DECLARE_JSON_TYPE(TcbVersion);
DECLARE_JSON_REQUIRED_FIELDS(TcbVersion, boot_loader, tee, snp, microcode);

using cpu_model = uint8_t; // This may need changing later...
struct TcbPolicy
{
cpu_model cpu_model;
pal::snp::TcbVersion tcb_version;

bool operator==(const TcbPolicy&) const = default;
};
DECLARE_JSON_TYPE(TcbPolicy);
DECLARE_JSON_REQUIRED_FIELDS(TcbPolicy, cpu_model, tcb_version);

} // namespace ccf::pal::snp
12 changes: 2 additions & 10 deletions include/ccf/service/tables/tcb_versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,10 @@

namespace ccf
{
using cpu_model = uint8_t; // This may need changing later...
struct SNP_TCB_Policy
{
cpu_model cpu_model;
pal::snp::TcbVersion tcb_version;
};
DECLARE_JSON_TYPE(SNP_TCB_Policy);
DECLARE_JSON_REQUIRED_FIELDS(SNP_TCB_Policy, cpu_model, tcb_version);

using SNPTCBVersionMap = ServiceSet<SNP_TCB_Policy>;
using SNPTcbVersionSet = ServiceSet<pal::snp::TcbPolicy>;
namespace Tables
{
static constexpr auto TCB_Version = "public:ccf.gov.nodes.snp.tcb_version";
static constexpr auto TCB_VERSION = "public:ccf.gov.nodes.snp.tcb_version";
}
}
116 changes: 81 additions & 35 deletions src/node/quote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,49 +232,58 @@ namespace ccf
return QuoteVerificationResult::Verified;
}

QuoteVerificationResult AttestationProvider::verify_quote_against_store(
ccf::kv::ReadOnlyTx& tx,
const QuoteInfo& quote_info,
const std::vector<uint8_t>& expected_node_public_key_der,
pal::PlatformAttestationMeasurement& measurement)
std::optional<pal::snp::TcbPolicy> AttestationProvider::get_snp_tcb_quote(
const QuoteInfo& quote_info)
{
ccf::crypto::Sha256Hash quoted_hash;
pal::PlatformAttestationReportData report_data;
try
{
pal::verify_quote(quote_info, measurement, report_data);
quoted_hash = report_data.to_sha256_hash();
}
catch (const std::exception& e)
switch (quote_info.format)
{
LOG_FAIL_FMT("Failed to verify attestation report: {}", e.what());
return QuoteVerificationResult::Failed;
}
case QuoteFormat::insecure_virtual:
{
LOG_FAIL_FMT("Cannot get TCB version from virtual attestation");
return std::nullopt;
}

auto rc = verify_host_data_against_store(tx, quote_info);
if (rc != QuoteVerificationResult::Verified)
{
return rc;
}
case QuoteFormat::amd_sev_snp_v1:
{
pal::snp::TcbPolicy version_quote = {};
pal::PlatformAttestationMeasurement d = {};
pal::PlatformAttestationReportData r = {};
try
{
pal::verify_quote(quote_info, d, r);
auto quote = *reinterpret_cast<const pal::snp::Attestation*>(
quote_info.quote.data());
version_quote = {
.cpu_model = quote.cpuid_fam_id, .tcb_version = quote.reported_tcb};
}
catch (const std::exception& e)
{
LOG_FAIL_FMT("Failed to verify attestation report: {}", e.what());
return std::nullopt;
}

rc = verify_enclave_measurement_against_store(
tx, measurement, quote_info.format, quote_info.uvm_endorsements);
if (rc != QuoteVerificationResult::Verified)
{
return rc;
}
return version_quote;
}

return verify_quoted_node_public_key(
expected_node_public_key_der, quoted_hash);
default:
{
return std::nullopt;
}
}
}

QuoteVerificationResult verify_tcb_version_against_store(
ccf::kv::ReadOnlyTx& tx, const QuoteInfo& quote_info)
{
switch (quote_info.format)
{
case QuoteFormat::insecure_virtual:
{
return QuoteVerificationResult::Verified;
}
case QuoteFormat::amd_sev_snp_v1:
{
auto policy = AttestationProvider::get_snp_tcb_quote(quote_info);
pal::PlatformAttestationMeasurement d = {};
pal::PlatformAttestationReportData r = {};
pal::verify_quote(quote_info, d, r);
Expand All @@ -288,20 +297,16 @@ namespace ccf
return QuoteVerificationResult::Verified;
}

SNP_TCB_Policy expected_policy = {
pal::snp::TcbPolicy expected_policy = {
.cpu_model = attestation.cpuid_fam_id,
.tcb_version = attestation.reported_tcb};
if (!tx.ro<SNPTCBVersionMap>(Tables::TCB_Version)
if (!tx.ro<SNPTcbVersionSet>(Tables::TCB_VERSION)
->contains(expected_policy))
{
return QuoteVerificationResult::FailedTCBVersionNotFound;
}
return QuoteVerificationResult::Verified;
}
case QuoteFormat::insecure_virtual:
{
return QuoteVerificationResult::Verified;
}
default:
{
throw std::logic_error(fmt::format(
Expand All @@ -310,4 +315,45 @@ namespace ccf
}
}
}
QuoteVerificationResult AttestationProvider::verify_quote_against_store(
ccf::kv::ReadOnlyTx& tx,
const QuoteInfo& quote_info,
const std::vector<uint8_t>& expected_node_public_key_der,
pal::PlatformAttestationMeasurement& measurement)
{
ccf::crypto::Sha256Hash quoted_hash;
pal::PlatformAttestationReportData report_data;
try
{
pal::verify_quote(quote_info, measurement, report_data);
quoted_hash = report_data.to_sha256_hash();
}
catch (const std::exception& e)
{
LOG_FAIL_FMT("Failed to verify attestation report: {}", e.what());
return QuoteVerificationResult::Failed;
}

auto rc = verify_host_data_against_store(tx, quote_info);
if (rc != QuoteVerificationResult::Verified)
{
return rc;
}

rc = verify_enclave_measurement_against_store(
tx, measurement, quote_info.format, quote_info.uvm_endorsements);
if (rc != QuoteVerificationResult::Verified)
{
return rc;
}

rc = verify_tcb_version_against_store(tx, quote_info);
if (rc != QuoteVerificationResult::Verified)
{
return rc;
}

return verify_quoted_node_public_key(
expected_node_public_key_der, quoted_hash);
}
}
16 changes: 14 additions & 2 deletions src/pal/test/snp_tcb_verification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
#include "ccf/pal/snp_tcb_version.h"
#include "ccf/kv/serialisers/json_serialiser.h"

#include "ccf/node/quote.h"

#include <random>
#include <span>
#include <string>

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

TEST_CASE("Test serializers for TcbVersion")
TEST_CASE("TcbVersion serialisation")
{
using namespace ccf::pal;

Expand All @@ -24,6 +26,16 @@ TEST_CASE("Test serializers for TcbVersion")

auto ser = ccf::kv::serialisers::JsonSerialiser<snp::TcbVersion>::to_serialised(tcb_version);
auto des_tcb_version = ccf::kv::serialisers::JsonSerialiser<snp::TcbVersion>::from_serialised(ser);

CHECK_EQ(tcb_version, des_tcb_version);

snp::TcbPolicy policy = {
.cpu_model = 1,
.tcb_version = tcb_version,
};

ser = ccf::kv::serialisers::JsonSerialiser<snp::TcbPolicy>::to_serialised(policy);
auto des_policy = ccf::kv::serialisers::JsonSerialiser<snp::TcbPolicy>::from_serialised(ser);

CHECK_EQ(policy, des_policy);
}

0 comments on commit 8b5aefd

Please sign in to comment.