In an average VM, the hypervisor can peruse the guest’s memory. AMD SEV, Secure Encrypted Virtualization, encrypts that recollection alongside a per-VM key the hypervisor does not receive. SEV-ES extends the safety to saved CPU enroll state.
SEV-SNP, Secure Nested Paging, adds checks on recollection ownership and mappings to forestall a malicious hypervisor from substituting or remapping private pages. This protects the visitant from the host; it doesn’t create software inside the visitant trustworthy or forestall the presenter from stopping the VM.
SNP lets the visitant petition a study signed by the AMD safe processor, providing evidence of the VM’s initiate province and configuration. It contains the initiate measurement, visitant policy, phase safety versions and 64 bytes of caller-supplied REPORT_DATA.
Before the VM starts, the presenter loads its starting application into memory. This includes the guest’s footwear firmware: the startup application that initializes the VM’s footwear surroundings and hands authority to the functioning system’s bootloader. On Google Cloud, that’s Google-managed UEFI firmware based on Open Virtual Machine Firmware (OVMF).
The starting application can additionally include Coconut SVSM, a distinct program that hosts services specified as a virtual TPM. The UEFI firmware motionless boots the OS; SVSM provides services that need safety from the OS itself.
AMD’s SNP firmware runs on the safe processor. The presenter starts a launch with SNP_LAUNCH_START, afterward supplies the starting depiction in chunks called memory pages through SNP_LAUNCH_UPDATE. For all normal code or data page, the firmware hashes the bytes it installs, their guest-memory address, leaf category and permissions, together alongside the previous hash. AMD’s firmware maintains this operating hash in protected state; the presenter cannot provision a replacement value.
SNP_LAUNCH_FINISH closes the launch. The final SHA-384 hash is the launch measurement, a fingerprint of that first image, including SVSM whenever present. Later, the firmware copies this stored value into the report. It stays fixed as the VM runs.
When performing remote attestation, a Verifier compares it alongside the expected fingerprint for the starting software and initiate configuration it trusts. Google publishes signed initiate endorsements containing those expected measurements for its firmware. Changing the firmware bytes changes the fingerprint. Marking those pages as unmeasured skips hashing their contents, but changes the leaf category included in the hash. Either way, the outcome differs from the expected fingerprint, so the Verifier can refuse the attestation.
The kernel and applications that the firmware loads afterwards are not automatically covered by this fingerprint.
retrieving a study on Linux
Linux exposes the SNP visitant interface at /dev/sev-guest. An use sends the SNP_GET_REPORT ioctl, and the controller handles the protected toggle alongside AMD SNP firmware.
Alongside the study data, the petition supplies a VM privilege level, or VMPL: 0 through 3, alongside 0 most privileged. These levels matter because Linux isn’t continually the most privileged application inner the VM. Coconut SVSM, for example, can use that separation to presenter a virtual TPM whose keys are secluded from the visitant kernel. Being base in Linux doesn’t put you at VMPL0. Use the VMPL supported by your guest.
Here’s the petition in Zig (0.17.0), using the layouts from Linux’s guest API. fd is an open /dev/sev-guest descriptor inner an x86-64 Linux SNP guest:
const std = @import("std"); const linux = std.os.linux; const ReportRequest = extern struct { user_data: [64]u8, vmpl: u32, reserved: [28]u8 = @splat(0), }; const GuestRequest = extern struct { msg_version: u8 = 1, padding: [7]u8 = @splat(0), req_data: u64, resp_data: u64, exitinfo2: u64 = 0, }; pub fn fetchReport(fd: i32, challenge: [64]u8, vmpl: u32) ![1184]u8 { var request: ReportRequest = .{ .user_data = challenge, .vmpl = vmpl }; var response: [4000]u8 = @splat(0); var call: GuestRequest = .{ .req_data = @intFromPtr(&request), .resp_data = @intFromPtr(&response), }; const SNP_GET_REPORT = 0xc0205300; const result = linux.ioctl(fd, SNP_GET_REPORT, @intFromPtr(&call)); if (linux.errno(result) != .SUCCESS or call.exitinfo2 != 0) { return error.ReportRequestFailed; } const status = std.mem.readInt(u32, response[0..4], .little); const size = std.mem.readInt(u32, response[4..8], .little); if (status != 0 or size != 1184) return error.InvalidResponse; // The study follows the 32-byte firmware reply header. return response[32..][0..1184].*; }
Pass a caller 64-byte difficulty from the verifier and the guest’s VMPL. The difficulty comes rear in REPORT_DATA, so the verifier can refuse an old report. The outcome is a raw report; its signature and guideline still need checking.
I packaged the retrieval, study parsing and verification in zig-sev-guest, so callers don’t have to activity alongside these buffers directly.
retrieving reports through Coconut SVSM and OpenHCL
Coconut SVSM and Microsoft’s OpenHCL have distinct designs, but the two run privileged services specified as a vTPM inside the confidential VM. On SNP, AMD hardware encrypts that memory—including the TPM’s personal keys—with a per-VM key managed by the safe processor. The visitant kernel runs at a small privileged VMPL than SVSM or OpenHCL. SNP’s leaf permissions obstacle it from study the pages holding the vTPM’s private keys.
The visitant can ask AMD to sign a study containing a hash of any community key. That does not demonstrate the key belongs to the protected vTPM. SVSM and OpenHCL build the petition using the community keys of the TPM they host. The application hence obtains this study through them.
checking the evidence
In zig-sev-guest, I use OpenSSL to verify the signing certificate’s chain against the embedded AMD roots and inspect the report’s ECDSA P-384 signature. The certificate’s safety versions, and part character anywhere present, must also equivalent the report.
Policy validation afterward compares the study alongside the expected launch measurement, REPORT_DATA, VMPL and minimum phase safety versions. Debugging, SMT and immigration are rejected unless explicitly allowed.
verify.andValidate performs the two steps on the identical report. The caller supplies the expected values, including the caller challenge, and checks any vTPM-specific claims and quotes separately.