Index | Thread | Search

From:
Hans-Jörg Höxer <hshoexer@genua.de>
Subject:
SEV-ES: vmd(8): Initial state encryption for SEV-ES guests 2/2
To:
<tech@openbsd.org>
Date:
Wed, 21 May 2025 16:07:28 +0200

Download raw body.

Thread
Hi,

second bit for vmd(8):  When launching a SEV-ES guest, we have to ask
the psp(4) to initially encrypt the VMSA.

Take care,
HJ.

--------------------------------------------------------------------------
commit 7678920aca8a51bc4c3ead181916e2036b46a8f3
Author: Hans-Joerg Hoexer <hshoexer@genua.de>
Date:   Wed Jun 5 18:59:26 2024 +0200

    vmd(8): Initial state encryption for SEV-ES guests

    For SEV-ES enabled guest send the LAUNCH ENCRYPT STATE command to
    psp(4), so the VMSA gets encrypted.  Refactor code of the launch
    protocol.

diff --git a/usr.sbin/vmd/psp.c b/usr.sbin/vmd/psp.c
index aa5a53bb4bd..da6c521f823 100644
--- a/usr.sbin/vmd/psp.c
+++ b/usr.sbin/vmd/psp.c
@@ -173,6 +173,27 @@ psp_launch_update(uint32_t handle, vaddr_t v, size_t len)
  * the PSP, the measurement is not really meaningful.  Thus we just
  * log it for now.
  */
+int
+psp_encrypt_state(uint32_t handle, uint32_t asid, uint32_t vmid,
+    uint32_t vcpuid)
+{
+	struct psp_encrypt_state es;
+
+	memset(&es, 0, sizeof(es));
+	es.handle = handle;
+	es.asid = asid;
+	es.vmid = vmid;
+	es.vcpuid = vcpuid;
+
+	if (ioctl(env->vmd_psp_fd, PSP_IOC_ENCRYPT_STATE, &es) < 0) {
+		log_warn("%s: ioctl", __func__);
+		return (-1);
+	}
+
+	return (0);
+}
+
+
 int
 psp_launch_measure(uint32_t handle)
 {
diff --git a/usr.sbin/vmd/sev.c b/usr.sbin/vmd/sev.c
index 752bb37d163..c2add19bfd9 100644
--- a/usr.sbin/vmd/sev.c
+++ b/usr.sbin/vmd/sev.c
@@ -148,7 +148,6 @@ sev_encrypt_memory(struct vmd_vm *vm)
 	struct vm_create_params *vcp = &vmc->vmc_params;
 	struct vm_mem_range	*vmr;
 	size_t			 i;
-	uint8_t			 gstate;
 
 	if (!vcp->vcp_sev)
 		return (0);
@@ -167,23 +166,6 @@ sev_encrypt_memory(struct vmd_vm *vm)
 		log_debug("%s: encrypted %zu:0x%lx size 0x%lx", __func__, i,
 		    vmr->vmr_va, vmr->vmr_size);
 	}
-	if (psp_launch_measure(vm->vm_sev_handle)) {
-		log_warnx("%s: failed to launch measure", __func__);
-		return (-1);
-	}
-	if (psp_launch_finish(vm->vm_sev_handle)) {
-		log_warnx("%s: failed to launch finish", __func__);
-		return (-1);
-	}
-
-	if (psp_get_gstate(vm->vm_sev_handle, NULL, NULL, &gstate)) {
-		log_warnx("%s: failed to get guest state", __func__);
-		return (-1);
-	}
-	if (gstate != PSP_GSTATE_RUNNING) {
-		log_warnx("%s: invalid guest state: 0x%hx", __func__, gstate);
-		return (-1);
-	}
 
 	return (0);
 }
@@ -222,6 +204,57 @@ sev_activate(struct vmd_vm *vm, int vcpu_id)
 }
 
 
+int
+sev_encrypt_state(struct vmd_vm *vm, int vcpu_id)
+{
+	struct vmop_create_params *vmc = &vm->vm_params;
+	struct vm_create_params *vcp = &vmc->vmc_params;
+
+	if (!vcp->vcp_seves)
+		return (0);
+
+	if (psp_encrypt_state(vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id],
+	    vcp->vcp_id, vcpu_id)) {
+		log_warnx("%s: failed to encrypt statet: 0x%x 0x%x 0x%0x 0x%0x",
+		    __func__, vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id],
+		    vm->vm_vmid, vcpu_id);
+		return (-1);
+	}
+
+	return (0);
+}
+
+int
+sev_launch_finalize(struct vmd_vm *vm)
+{
+	struct vmop_create_params *vmc = &vm->vm_params;
+	struct vm_create_params *vcp = &vmc->vmc_params;
+	uint8_t		gstate;
+
+	if (!vcp->vcp_sev)
+		return (0);
+
+	if (psp_launch_measure(vm->vm_sev_handle)) {
+		log_warnx("%s: failed to launch measure", __func__);
+		return (-1);
+	}
+	if (psp_launch_finish(vm->vm_sev_handle)) {
+		log_warnx("%s: failed to launch finish", __func__);
+		return (-1);
+	}
+
+	if (psp_get_gstate(vm->vm_sev_handle, NULL, NULL, &gstate)) {
+		log_warnx("%s: failed to get guest state", __func__);
+		return (-1);
+	}
+	if (gstate != PSP_GSTATE_RUNNING) {
+		log_warnx("%s: invalid guest state: 0x%hx", __func__, gstate);
+		return (-1);
+	}
+
+	return (0);
+}
+
 /*
  * Deactivate and decommission a guest's SEV crypto state.
  */
diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c
index a9429dbd21d..acba8c81755 100644
--- a/usr.sbin/vmd/vm.c
+++ b/usr.sbin/vmd/vm.c
@@ -895,6 +895,18 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg_state *vrs)
 			}
 		}
 
+		if (sev_encrypt_state(current_vm, i)) {
+			log_warnx("%s: state encryption failed for VCPU "
+			    "%zu failed - exiting.", __progname, i);
+			return (EIO);
+		}
+
+		if (sev_launch_finalize(current_vm)) {
+			log_warnx("%s: state encryption failed for VCPU "
+			    "%zu failed - exiting.", __progname, i);
+			return (EIO);
+		}
+
 		ret = pthread_cond_init(&vcpu_run_cond[i], NULL);
 		if (ret) {
 			log_warnx("%s: cannot initialize cond var (%d)",
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index e0b7c27eb46..a8745e8a2a3 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -588,6 +588,7 @@ int	 psp_df_flush(void);
 int	 psp_get_gstate(uint32_t, uint32_t *, uint32_t *, uint8_t *);
 int	 psp_launch_start(uint32_t *, int);
 int	 psp_launch_update(uint32_t, vaddr_t, size_t);
+int	 psp_encrypt_state(uint32_t, uint32_t, uint32_t, uint32_t);
 int	 psp_launch_measure(uint32_t);
 int	 psp_launch_finish(uint32_t);
 int	 psp_activate(uint32_t, uint32_t);
@@ -599,6 +600,8 @@ int	sev_init(struct vmd_vm *);
 int	sev_register_encryption(vaddr_t, size_t);
 int	sev_encrypt_memory(struct vmd_vm *);
 int	sev_activate(struct vmd_vm *, int);
+int	sev_encrypt_state(struct vmd_vm *, int);
+int	sev_launch_finalize(struct vmd_vm *);
 int	sev_shutdown(struct vmd_vm *);
 
 #endif /* VMD_H */