зеркало из https://github.com/microsoft/CCF.git
264 строки
7.5 KiB
C++
264 строки
7.5 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the Apache 2.0 License.
|
|
#pragma once
|
|
|
|
#include "ccf/pal/attestation_sev_snp_endorsements.h"
|
|
#include "ccf/pal/measurement.h"
|
|
#include "ccf/pal/report_data.h"
|
|
|
|
#include <array>
|
|
#include <map>
|
|
#include <string>
|
|
|
|
namespace ccf::pal::snp
|
|
{
|
|
// Based on the SEV-SNP ABI Spec document at
|
|
// https://www.amd.com/system/files/TechDocs/56860.pdf
|
|
|
|
static constexpr auto NO_SECURITY_POLICY = "";
|
|
|
|
// From https://developer.amd.com/sev/
|
|
constexpr auto amd_milan_root_signing_public_key =
|
|
R"(-----BEGIN PUBLIC KEY-----
|
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsV
|
|
mD7FktuotWwX1fNgW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU
|
|
0V5tkKiU1EesNFta1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S
|
|
1ju8X93+6dxDUrG2SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI5
|
|
2Naz5m2B+O+vjsC060d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3K
|
|
FYXP59XmJgtcog05gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd
|
|
/y8KxX7jksTEzAOgbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBk
|
|
gnlENEWx1UcbQQrs+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V
|
|
9TJQqnN3Q53kt5viQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnq
|
|
z55I0u33wh4r0ZNQeTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+Og
|
|
pCCoMNit2uLo9M18fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXo
|
|
QPHfbkH0CyPfhl1jWhJFZasCAwEAAQ==
|
|
-----END PUBLIC KEY-----
|
|
)";
|
|
|
|
#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;
|
|
|
|
bool operator==(const TcbVersion&) const = default;
|
|
};
|
|
#pragma pack(pop)
|
|
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];
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
// 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;
|
|
};
|
|
#pragma pack(pop)
|
|
static_assert(
|
|
sizeof(GuestPolicy) == sizeof(uint64_t),
|
|
"Can't cast GuestPolicy to uint64_t");
|
|
|
|
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;
|
|
};
|
|
#pragma pack(pop)
|
|
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;
|
|
};
|
|
#pragma pack(pop)
|
|
static_assert(
|
|
sizeof(PlatformInfo) == sizeof(uint64_t),
|
|
"Can't cast PlatformInfo to uint64_t");
|
|
|
|
#pragma pack(push, 1)
|
|
// Table 21
|
|
|
|
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 */
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
static HostPort get_endpoint_loc(
|
|
const EndorsementsServer& server, const HostPort& default_values)
|
|
{
|
|
if (server.url.has_value())
|
|
{
|
|
auto url = server.url.value();
|
|
auto pos = url.find(':');
|
|
if (pos == std::string::npos)
|
|
{
|
|
return {url, default_values.port};
|
|
}
|
|
else
|
|
{
|
|
return {url.substr(0, pos), url.substr(pos + 1)};
|
|
}
|
|
}
|
|
|
|
return default_values;
|
|
}
|
|
|
|
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));
|
|
|
|
constexpr size_t default_max_retries_count = 10;
|
|
|
|
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,
|
|
chip_id_hex,
|
|
reported_tcb,
|
|
default_max_retries_count));
|
|
return config;
|
|
}
|
|
|
|
for (auto const& server : endorsements_servers)
|
|
{
|
|
size_t max_retries_count =
|
|
server.max_retries_count.value_or(default_max_retries_count);
|
|
switch (server.type)
|
|
{
|
|
case EndorsementsEndpointType::Azure:
|
|
{
|
|
auto loc =
|
|
get_endpoint_loc(server, default_azure_endorsements_endpoint);
|
|
config.servers.emplace_back(make_azure_endorsements_server(
|
|
loc, chip_id_hex, reported_tcb, max_retries_count));
|
|
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 loc =
|
|
get_endpoint_loc(server, default_amd_endorsements_endpoint);
|
|
config.servers.emplace_back(make_amd_endorsements_server(
|
|
loc,
|
|
chip_id_hex,
|
|
boot_loader,
|
|
tee,
|
|
snp,
|
|
microcode,
|
|
max_retries_count));
|
|
break;
|
|
}
|
|
case EndorsementsEndpointType::THIM:
|
|
{
|
|
auto loc =
|
|
get_endpoint_loc(server, default_thim_endorsements_endpoint);
|
|
config.servers.emplace_back(make_thim_endorsements_server(
|
|
loc, chip_id_hex, reported_tcb, max_retries_count));
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
throw std::logic_error(fmt::format(
|
|
"Unsupported endorsements server type: {}", server.type));
|
|
}
|
|
}
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
class AttestationInterface
|
|
{
|
|
public:
|
|
virtual const snp::Attestation& get() const = 0;
|
|
virtual std::vector<uint8_t> get_raw() = 0;
|
|
|
|
virtual ~AttestationInterface() = default;
|
|
};
|
|
}
|