Collect the SEV chip unique ID and the SNP reported TCB version. These identify the exact VCEK a remote attestation client needs to fetch from AMD's KDS for a given host, and are exposed alongside the existing capability flags. Signed-off-by: Christian Ludwig --- .../query-machine-capabilities.c | 81 ++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/src/query-machine-capabilities/query-machine-capabilities.c b/src/query-machine-capabilities/query-machine-capabilities.c index b7e06286..088b2683 100644 --- a/src/query-machine-capabilities/query-machine-capabilities.c +++ b/src/query-machine-capabilities/query-machine-capabilities.c @@ -6,7 +6,10 @@ #include #include #include +#include #include +#include +#include #ifdef __aarch64__ #include @@ -28,6 +31,9 @@ typedef struct { bool sev_support; bool sev_es_support; bool sev_snp_support; + uint8_t *sev_chip_id; + size_t sev_chip_id_len; + uint64_t sev_snp_reported_tcb_version; uint8_t cbitpos; uint8_t reduced_phys_bits; @@ -123,7 +129,11 @@ int read_msr(uint32_t msr_index, uint64_t *value) { void query_cpu_capabilities_sev(cpu_caps_amd_sev_t *res) { #ifdef __x86_64__ + int fd, ret; uint32_t eax, ebx, ecx, edx; + struct sev_issue_cmd cmd; + struct sev_user_data_snp_status snp_status; + struct sev_user_data_get_id2 get_id; struct { const char *path; bool *result; @@ -170,6 +180,64 @@ void query_cpu_capabilities_sev(cpu_caps_amd_sev_t *res) { res->cbitpos = ebx & 0x3f; res->reduced_phys_bits = (ebx >> 6) & 0x3f; + /* + * Get ChipId and TCB_VERSION for an Attester. + * Only necessary for SEV-SNP. + */ + if (!res->sev_snp_support) + return; + + fd = open("/dev/sev", O_RDWR); + if (fd < 0) + return; + + memset(&snp_status, 0, sizeof(snp_status)); + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = SNP_PLATFORM_STATUS; + cmd.data = (uintptr_t)&snp_status; + ret = ioctl(fd, SEV_ISSUE_CMD, &cmd); + if (ret >= 0 && cmd.error == 0) { + res->sev_snp_reported_tcb_version = snp_status.reported_tcb_version; + } else if (cmd.error != 0) { + fprintf(stderr, "SEV firmware error: 0x%x\n", cmd.error); + } + + /* + * Get ChipId. The ID length must not be assumed, so ask for it first by + * passing a zero-length buffer. That query is expected to fail with + * INVALID_LEN; the firmware reports the required length either way. + */ + memset(&get_id, 0, sizeof(get_id)); + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = SEV_GET_ID2; + cmd.data = (uintptr_t)&get_id; + ioctl(fd, SEV_ISSUE_CMD, &cmd); + if (get_id.length == 0) + goto skip_chip_id; + + res->sev_chip_id = malloc(get_id.length); + if (res->sev_chip_id == NULL) { + perror("malloc"); + goto skip_chip_id; + } + res->sev_chip_id_len = get_id.length; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = SEV_GET_ID2; + cmd.data = (uintptr_t)&get_id; + get_id.address = (uintptr_t)res->sev_chip_id; + get_id.length = res->sev_chip_id_len; + ret = ioctl(fd, SEV_ISSUE_CMD, &cmd); + if (ret < 0 || cmd.error != 0 || get_id.length != res->sev_chip_id_len) { + if (cmd.error != 0) + fprintf(stderr, "SEV firmware error: 0x%x\n", cmd.error); + free(res->sev_chip_id); + res->sev_chip_id = NULL; + res->sev_chip_id_len = 0; + goto skip_chip_id; + } +skip_chip_id: + close(fd); #else memset(res, 0, sizeof(*res)); #endif @@ -240,6 +308,11 @@ int main() { if (strncmp(vendor, "AuthenticAMD", 12) == 0) { cpu_caps_amd_sev_t caps_sev = { 0 }; query_cpu_capabilities_sev(&caps_sev); + char sev_chip_id[(caps_sev.sev_chip_id_len * 2) + 1]; + + memset(sev_chip_id, 0, (caps_sev.sev_chip_id_len * 2) + 1); + for (size_t i = 0; i < caps_sev.sev_chip_id_len; i++) + sprintf(&sev_chip_id[i*2], "%02x", caps_sev.sev_chip_id[i]); ret = fprintf(file, " \"amd-sev\": {" @@ -247,13 +320,17 @@ int main() { " \"reduced-phys-bits\": %u," " \"sev-support\": %s," " \"sev-support-es\": %s," - " \"sev-support-snp\": %s" + " \"sev-support-snp\": %s," + " \"sev-chip-id\": \"0x%s\"," + " \"sev-snp-tcb-version\": \"0x%016" PRIX64 "\"" " }", caps_sev.cbitpos, caps_sev.reduced_phys_bits, caps_sev.sev_support ? "true" : "false", caps_sev.sev_es_support ? "true" : "false", - caps_sev.sev_snp_support ? "true" : "false" + caps_sev.sev_snp_support ? "true" : "false", + sev_chip_id, + caps_sev.sev_snp_reported_tcb_version ); } else if (strncmp(vendor, "GenuineIntel", 12) == 0) { cpu_caps_intel_tdx_t caps_tdx; -- 2.34.1