Skip to content

Instantly share code, notes, and snippets.

@dubek
Created June 8, 2023 12:27
Show Gist options
  • Save dubek/0e0a419fecf2ca87dd65d483d5c446d5 to your computer and use it in GitHub Desktop.
Save dubek/0e0a419fecf2ca87dd65d483d5c446d5 to your computer and use it in GitHub Desktop.
Guest userspace program to retrieve attestation report from SVSM
/*
* gcc -O2 -Wall -static -s svsm-report-2.c -o svsm-report-2
*/
#include <fcntl.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
/* from linux/sev-guest.h */
struct snp_guest_request_ioctl {
/* message version number (must be non-zero) */
uint8_t msg_version;
/* Request and response structure address */
uint64_t req_data;
uint64_t resp_data;
/* firmware error code on failure (see psp-sev.h) */
uint64_t fw_err;
};
/************************************************************/
/* */
/* SVSM_ATTEST_SERVICES ioctl call */
/* */
/************************************************************/
#define SNP_GUEST_REQ_IOC_TYPE 'S'
#define SNP_SVSM_ATTEST_SERVICES _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x3, struct snp_guest_request_ioctl)
struct snp_svsm_attest_services_req {
/* nonce that should be included in the report */
uint8_t nonce[32];
/* where to copy the certificate blob */
uint64_t certs_address;
/* length of the certificate blob */
uint32_t certs_len;
};
struct snp_svsm_attest_services_resp {
/* length of the returned attestation report */
uint32_t report_len;
/* length of the returned services manifest */
uint32_t services_manifest_len;
/* length of the returned certificates blob */
uint32_t certs_len;
uint8_t rsvd[4];
/* services manifest */
uint8_t services_manifest[1024];
/* attestation report, see SEV-SNP spec for the format */
uint8_t report[3000];
};
/************************************************************/
static const uint8_t nonce[32] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
int main(int argc, char *argv[]) {
struct snp_svsm_attest_services_req snp_request;
struct snp_svsm_attest_services_resp snp_response;
struct snp_guest_request_ioctl ioctl_request;
int snpdev, fd, rc;
snpdev = open("/dev/sev-guest", O_RDWR | O_CLOEXEC);
if (snpdev < 0) {
printf("Failed to open /dev/sev-guest\n");
return 1;
}
uint8_t *certs = malloc(4 * 4096);
memset(&snp_request, 0, sizeof(snp_request));
memcpy(snp_request.nonce, nonce, sizeof(snp_request.nonce));
snp_request.certs_address = (uint64_t)certs;
snp_request.certs_len = 4 * 4096;
memset(&snp_response, 0, sizeof(snp_response));
memset(&ioctl_request, 0, sizeof(ioctl_request));
ioctl_request.msg_version = 1;
ioctl_request.req_data = (uint64_t)&snp_request;
ioctl_request.resp_data = (uint64_t)&snp_response;
rc = ioctl(snpdev, SNP_SVSM_ATTEST_SERVICES, &ioctl_request);
if (rc < 0) {
printf("ioctl SNP_SVSM_ATTEST_SERVICES failed\n");
return 1;
}
printf("SVSM call response:\n");
printf(">> ioctl_request.fw_err=0x%lx\n", ioctl_request.fw_err);
printf(">> snp_response.report_len=0x%x\n", snp_response.report_len);
printf(">> snp_response.services_manifest_len=0x%x\n", snp_response.services_manifest_len);
printf(">> snp_response.certs_len=0x%x\n", snp_response.certs_len);
fd = open("./attestation_report.bin", O_CREAT | O_WRONLY);
write(fd, snp_response.report, snp_response.report_len);
close(fd);
printf("Wrote: ./attestation_report.bin\n");
fd = open("./services_manifest", O_CREAT | O_WRONLY);
write(fd, snp_response.services_manifest, snp_response.services_manifest_len);
close(fd);
printf("Wrote: ./services_manifest.bin\n");
fd = open("./certs", O_CREAT | O_WRONLY);
write(fd, certs, snp_response.certs_len);
close(fd);
printf("Wrote: ./certs.bin\n");
free(certs);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment