diff --git a/src/runtime/Makefile b/src/runtime/Makefile index 69c86974c2..da91a71611 100644 --- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -150,6 +150,7 @@ FIRMWARETDVFVOLUMEPATH := FIRMWARESEVPATH := $(PREFIXDEPS)/share/ovmf/OVMF.fd FIRMWARESNPPATH := $(PREFIXDEPS)/share/ovmf/AMDSEV.fd +SNPCERTSPATH := /opt/snp/cert_chain.cert ROOTMEASURECONFIG ?= "" KERNELPARAMS += $(ROOTMEASURECONFIG) @@ -679,6 +680,7 @@ USER_VARS += FIRMWARETDVFPATH USER_VARS += FIRMWAREVOLUMEPATH USER_VARS += FIRMWARETDVFVOLUMEPATH USER_VARS += FIRMWARESNPPATH +USER_VARS += SNPCERTSPATH USER_VARS += MACHINEACCELERATORS USER_VARS += CPUFEATURES USER_VARS += TDXCPUFEATURES diff --git a/src/runtime/config/configuration-qemu-snp.toml.in b/src/runtime/config/configuration-qemu-snp.toml.in index 38bec359d8..c655c8db1b 100644 --- a/src/runtime/config/configuration-qemu-snp.toml.in +++ b/src/runtime/config/configuration-qemu-snp.toml.in @@ -44,6 +44,11 @@ confidential_guest = true # enable SEV SNP VMs sev_snp_guest = true +# The path to the file containing the SNP certificate chain (including +# VCEK/VLEK certificates). This wil be used to get the extended attestation +# report from the guest. The default path is @SNPCERTSPATH@. +snp_certs_path = "@SNPCERTSPATH@" + # Enable running QEMU VMM as a non-root user. # By default QEMU VMM run as root. When this is set to true, QEMU VMM process runs as # a non-root random user. See documentation for the limitations of this mode. diff --git a/src/runtime/pkg/govmm/qemu/qemu.go b/src/runtime/pkg/govmm/qemu/qemu.go index e752f81814..6d71e28f93 100644 --- a/src/runtime/pkg/govmm/qemu/qemu.go +++ b/src/runtime/pkg/govmm/qemu/qemu.go @@ -300,6 +300,10 @@ type Object struct { // and UEFI program image. FirmwareVolume string + // The path to the file containing the AMD SEV-SNP certificate chain + // (including VCEK/VLEK certificates). + SnpCertsPath string + // CBitPos is the location of the C-bit in a guest page table entry // This is only relevant for sev-guest objects CBitPos uint32 @@ -388,6 +392,9 @@ func (object Object) QemuParams(config *Config) []string { objectParams = append(objectParams, fmt.Sprintf("cbitpos=%d", object.CBitPos)) objectParams = append(objectParams, fmt.Sprintf("reduced-phys-bits=%d", object.ReducedPhysBits)) objectParams = append(objectParams, "kernel-hashes=on") + if object.SnpCertsPath != "" { + objectParams = append(objectParams, fmt.Sprintf("certs-path=%s", object.SnpCertsPath)) + } driveParams = append(driveParams, "if=pflash,format=raw,readonly=on") driveParams = append(driveParams, fmt.Sprintf("file=%s", object.File)) diff --git a/src/runtime/pkg/katautils/config-settings.go.in b/src/runtime/pkg/katautils/config-settings.go.in index bd57d30875..bebf5a0224 100644 --- a/src/runtime/pkg/katautils/config-settings.go.in +++ b/src/runtime/pkg/katautils/config-settings.go.in @@ -117,3 +117,5 @@ const defaultPCIeSwitchPort = 0 const defaultRemoteHypervisorSocket = "/run/peerpod/hypervisor.sock" const defaultRemoteHypervisorTimeout = 600 + +const defaultSnpCertsPath = "/opt/snp/cert_chain.cert" diff --git a/src/runtime/pkg/katautils/config.go b/src/runtime/pkg/katautils/config.go index 5d2a655d68..627dafa47c 100644 --- a/src/runtime/pkg/katautils/config.go +++ b/src/runtime/pkg/katautils/config.go @@ -106,6 +106,7 @@ type hypervisor struct { SeccompSandbox string `toml:"seccompsandbox"` BlockDeviceAIO string `toml:"block_device_aio"` RemoteHypervisorSocket string `toml:"remote_hypervisor_socket"` + SnpCertsPath string `toml:"snp_certs_path"` HypervisorPathList []string `toml:"valid_hypervisor_paths"` JailerPathList []string `toml:"valid_jailer_paths"` CtlPathList []string `toml:"valid_ctlpaths"` @@ -295,6 +296,24 @@ func (h hypervisor) firmware() (string, error) { return ResolvePath(p) } +func (h hypervisor) snpCertsPath() (string, error) { + p := h.SnpCertsPath + + if p == "" { + p = defaultSnpCertsPath + } + + path, err := ResolvePath(p) + if err != nil { + if p == defaultSnpCertsPath { + msg := fmt.Sprintf("failed to resolve SNP certificates path: %s", defaultSnpCertsPath) + kataUtilsLogger.Warn(msg) + return "", nil + } + } + return path, err +} + func (h hypervisor) coldPlugVFIO() config.PCIePort { if h.ColdPlugVFIO == "" { return defaultColdPlugVFIO @@ -850,6 +869,11 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { return vc.HypervisorConfig{}, err } + snpCertsPath, err := h.snpCertsPath() + if err != nil { + return vc.HypervisorConfig{}, err + } + machineAccelerators := h.machineAccelerators() cpuFeatures := h.cpuFeatures() kernelParams := h.kernelParams() @@ -914,6 +938,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { RootfsType: rootfsType, FirmwarePath: firmware, FirmwareVolumePath: firmwareVolume, + SnpCertsPath: snpCertsPath, PFlash: pflashes, MachineAccelerators: machineAccelerators, CPUFeatures: cpuFeatures, diff --git a/src/runtime/virtcontainers/hypervisor.go b/src/runtime/virtcontainers/hypervisor.go index aa30823247..cc37433105 100644 --- a/src/runtime/virtcontainers/hypervisor.go +++ b/src/runtime/virtcontainers/hypervisor.go @@ -475,6 +475,10 @@ type HypervisorConfig struct { // The user maps to the uid. User string + // The path to the file containing the AMD SEV-SNP certificate chain + // (including VCEK/VLEK certificates). + SnpCertsPath string + // KernelParams are additional guest kernel parameters. KernelParams []Param diff --git a/src/runtime/virtcontainers/qemu_amd64.go b/src/runtime/virtcontainers/qemu_amd64.go index ade7356eb6..1d1be17118 100644 --- a/src/runtime/virtcontainers/qemu_amd64.go +++ b/src/runtime/virtcontainers/qemu_amd64.go @@ -33,6 +33,8 @@ type qemuAmd64 struct { sgxEPCSize int64 qgsPort uint32 + + snpCertsPath string } const ( @@ -125,9 +127,10 @@ func newQemuArch(config HypervisorConfig) (qemuArch, error) { protection: noneProtection, legacySerial: config.LegacySerial, }, - vmFactory: factory, - snpGuest: config.SevSnpGuest, - qgsPort: config.QgsPort, + vmFactory: factory, + snpGuest: config.SevSnpGuest, + qgsPort: config.QgsPort, + snpCertsPath: config.SnpCertsPath, } if config.ConfidentialGuest { @@ -311,6 +314,7 @@ func (q *qemuAmd64) appendProtectionDevice(devices []govmmQemu.Device, firmware, File: firmware, CBitPos: cpuid.AMDMemEncrypt.CBitPosition, ReducedPhysBits: 1, + SnpCertsPath: q.snpCertsPath, }), "", nil case noneProtection: