38 static void verify_snp_attestation_report(
45 throw std::logic_error(fmt::format(
46 "Unexpected attestation report to verify for SEV-SNP: {}",
52 throw std::logic_error(fmt::format(
53 "Input SEV-SNP attestation report is not of expected size {}: {}",
55 quote_info.
quote.size()));
61 if (quote.version < snp::minimum_attestation_version)
63 throw std::logic_error(fmt::format(
64 "SEV-SNP: Attestation version is {} not >= expected minimum {}",
66 snp::minimum_attestation_version));
69 if (quote.flags.signing_key != snp::attestation_flags_signing_key_vcek)
71 throw std::logic_error(fmt::format(
72 "SEV-SNP: Attestation report must be signed by VCEK: {}",
73 static_cast<uint8_t
>(quote.flags.signing_key)));
76 if (quote.flags.mask_chip_key != 0)
78 throw std::logic_error(
79 fmt::format(
"SEV-SNP: Mask chip key must not be set"));
91 throw std::logic_error(fmt::format(
92 "SEV-SNP: VMPL for guest attestations must be in 0-3 range, not {}",
100 reinterpret_cast<const char*
>(quote_info.
endorsements.data()),
102 if (certificates.size() != 3)
104 throw std::logic_error(fmt::format(
105 "Expected 3 endorsement certificates but got {}", certificates.size()));
110 auto chip_certificate = certificates[0];
111 auto sev_version_certificate = certificates[1];
112 auto root_certificate = certificates[2];
116 std::string expected_root_public_key;
117 if (quote.version < 3)
129 throw std::logic_error(fmt::format(
130 "SEV-SNP: Unsupported CPUID family {} model {}",
132 quote.cpuid_mod_id));
134 expected_root_public_key = key->second;
136 if (root_cert_verifier->public_key_pem().str() != expected_root_public_key)
138 throw std::logic_error(fmt::format(
139 "SEV-SNP: The root of trust public key for this attestation was not "
140 "the expected one for v{} {} {}: {} != {}",
144 root_cert_verifier->public_key_pem().str(),
145 expected_root_public_key));
148 if (!root_cert_verifier->verify_certificate({&root_certificate}))
150 throw std::logic_error(
151 "SEV-SNP: The root of trust public key for this attestation was not "
152 "self signed as expected");
156 if (!chip_cert_verifier->verify_certificate(
157 {&root_certificate}, {&sev_version_certificate}))
159 throw std::logic_error(
160 "SEV-SNP: The chain of signatures from the root of trust to this "
161 "attestation is broken");
167 throw std::logic_error(fmt::format(
168 "SEV-SNP: Unsupported signature algorithm: {} (supported: {})",
169 quote.signature_algo,
176 sizeof(quote.signature.r),
178 sizeof(quote.signature.s),
182 std::span quote_without_signature{
183 quote_info.
quote.data(),
184 quote_info.
quote.size() -
sizeof(quote.signature)};
185 if (!chip_cert_verifier->verify(quote_without_signature, quote_signature))
187 throw std::logic_error(
188 "SEV-SNP: Chip certificate (VCEK) did not sign this attestation");
201 if (quote.policy.debug != 0)
203 throw std::logic_error(
204 "SEV-SNP: SNP attestation report guest policy debugging must not be "
208 if (quote.policy.migrate_ma != 0)
210 throw std::logic_error(
"SEV-SNP: Migration agents must not be enabled");
216 const auto& endorsed_tcb = quote_info.
endorsed_tcb.value();
217 auto raw_tcb = ds::from_hex(quote_info.
endorsed_tcb.value());
221 throw std::logic_error(fmt::format(
222 "SEV-SNP: TCB of size {}, expected {}",
228 if (tcb != quote.reported_tcb)
230 auto* reported_tcb =
reinterpret_cast<uint8_t*
>("e.reported_tcb);
231 throw std::logic_error(fmt::format(
232 "SEV-SNP: endorsed TCB {} does not match reported TCB {}",
235 {reported_tcb, reported_tcb +
sizeof(quote.reported_tcb)})));
240#if (defined(INSIDE_ENCLAVE) && !defined(VIRTUAL_ENCLAVE)) || \
241 defined(SGX_ATTESTATION_VERIFICATION)
242 static void verify_sgx_quote(
244 PlatformAttestationMeasurement& measurement,
245 PlatformAttestationReportData& report_data)
249 throw std::logic_error(fmt::format(
250 "Unexpected attestation quote to verify for SGX: {}",
256 auto rc = oe_verify_evidence(
257 &sgx::oe_quote_format,
258 quote_info.
quote.data(),
259 quote_info.
quote.size(),
268 throw std::logic_error(fmt::format(
269 "Failed to verify evidence in SGX attestation report: {}",
273 std::optional<SgxAttestationMeasurement> claim_measurement = std::nullopt;
274 std::optional<SgxAttestationReportData> custom_claim_report_data =
276 for (
size_t i = 0; i < claims.length; i++)
278 auto& claim = claims.data[i];
279 auto claim_name = std::string(claim.name);
280 if (claim_name == OE_CLAIM_UNIQUE_ID)
282 if (claim.value_size != SgxAttestationMeasurement::size())
284 throw std::logic_error(
285 fmt::format(
"SGX measurement claim is not of expected size"));
291 else if (claim_name == OE_CLAIM_CUSTOM_CLAIMS_BUFFER)
294 sgx::CustomClaims custom_claims;
295 rc = oe_deserialize_custom_claims(
299 &custom_claims.length);
302 throw std::logic_error(fmt::format(
303 "Failed to deserialise custom claims in SGX attestation report",
307 for (
size_t j = 0; j < custom_claims.length; j++)
309 const auto& custom_claim = custom_claims.data[j];
310 if (std::string(custom_claim.name) == sgx::report_data_claim_name)
312 if (custom_claim.value_size != SgxAttestationReportData::size())
314 throw std::logic_error(fmt::format(
315 "Expected claim {} of size {}, had size {}",
316 sgx::report_data_claim_name,
317 SgxAttestationReportData::size(),
318 custom_claim.value_size));
322 {custom_claim.value, custom_claim.value_size});
330 if (!claim_measurement.has_value())
332 throw std::logic_error(
333 "Could not find measurement in SGX attestation report");
336 if (!custom_claim_report_data.has_value())
338 throw std::logic_error(
339 "Could not find report data in SGX attestation report");
342 measurement = claim_measurement.value();
343 report_data = custom_claim_report_data.value();
347#if defined(PLATFORM_VIRTUAL)
349 static void generate_quote(
350 PlatformAttestationReportData& report_data,
361#elif defined(PLATFORM_SNP)
363 static void generate_quote(
364 PlatformAttestationReportData& report_data,
368 QuoteInfo node_quote_info = {};
370 auto attestation = snp::get_attestation(report_data);
372 node_quote_info.quote = attestation->get_raw();
374 if (endorsement_cb !=
nullptr)
378 snp::make_endorsement_endpoint_configuration(
379 attestation->get(), endorsements_servers));
384#if !defined(INSIDE_ENCLAVE) || defined(VIRTUAL_ENCLAVE)
386 static void verify_quote(
387 const QuoteInfo& quote_info,
388 PlatformAttestationMeasurement& measurement,
389 PlatformAttestationReportData& report_data)
391 auto is_sev_snp = snp::is_sev_snp();
397 throw std::logic_error(
398 "Cannot verify virtual attestation report if node is SEV-SNP");
408 throw std::logic_error(
409 "Cannot verify SEV-SNP attestation report if node is virtual");
412 verify_snp_attestation_report(quote_info, measurement, report_data);
416# if defined(SGX_ATTESTATION_VERIFICATION)
417 verify_sgx_quote(quote_info, measurement, report_data);
421 throw std::logic_error(
422 "Cannot verify SGX attestation report if node is SEV-SNP");
426 throw std::logic_error(
427 "Cannot verify SGX attestation report if node is virtual");
435 static void generate_quote(
436 PlatformAttestationReportData& report_data,
440 QuoteInfo node_quote_info = {};
443 sgx::Evidence evidence;
444 sgx::Endorsements endorsements;
445 sgx::SerialisedClaims serialised_custom_claims;
447 const size_t custom_claim_length = 1;
448 oe_claim_t custom_claim;
449 custom_claim.name =
const_cast<char*
>(sgx::report_data_claim_name);
450 custom_claim.value = report_data.data.data();
451 custom_claim.value_size = report_data.data.size();
453 auto rc = oe_serialize_custom_claims(
456 &serialised_custom_claims.buffer,
457 &serialised_custom_claims.size);
460 throw std::logic_error(fmt::format(
461 "Could not serialise node's public key as quote custom claim: {}",
465 rc = oe_get_evidence(
466 &sgx::oe_quote_format,
468 serialised_custom_claims.buffer,
469 serialised_custom_claims.size,
474 &endorsements.buffer,
478 throw std::logic_error(
479 fmt::format(
"Failed to get evidence: {}",
oe_result_str(rc)));
482 node_quote_info.quote.assign(
483 evidence.buffer, evidence.buffer + evidence.size);
484 node_quote_info.endorsements.assign(
485 endorsements.buffer, endorsements.buffer + endorsements.size);
487 if (endorsement_cb !=
nullptr)
489 endorsement_cb(node_quote_info, {});
493 static void verify_quote(
494 const QuoteInfo& quote_info,
495 PlatformAttestationMeasurement& measurement,
496 PlatformAttestationReportData& report_data)
500 throw std::logic_error(fmt::format(
501 "Cannot verify virtual insecure attestation report on SGX platform"));
505 verify_snp_attestation_report(quote_info, measurement, report_data);
509 verify_sgx_quote(quote_info, measurement, report_data);