Unverified Commit 498497b4 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5258 [OLK-6.6] Support request attestation report from CSV guest

Merge Pull Request from: @hanliyang 
 
Support request attestation report from CSV guest

issue:
https://gitee.com/open_euler/dashboard?issue_id=I98W95

The ATTESTATION function allows the users of CSV virtual machine to obtain an attestation report, and the 3rd party can verify the identity of the user. The attestation report contains the key authentication information of the CSV virtual machine and is signed by the PSP. The plaintext of the attestation report can only be obtained inside the CSV virtual machine, VMM and system software of the host can not spy and forge the attestation report.

To support this functionality, the CSV virtual machine kernel uses a similar approach to confidential computing virtual machines such as SEV, providing an ioctl interface through a csv-guest driver, through which the user of CSV virtual machine initiates hypercall requests. KVM converts hypercall requests into ATTESTATION API requests and sends them to the PSP.

The CSV virtual machine kernel must be compiled with the following configuration:
CONFIG_HYGON_CSV=y
CONFIG_VIRT_DRIVERS=y
CONFIG_CSV_GUEST=m

Test:
1. boot and login to the CSV guest, and install csv-guest kernel module
2. Run ioclt-get-attestation in the CSV guest, which will generate a report.cert file and send it to 'machine2'
3. Use he gadget verify-attestation on 'machine2' to verify the attestation report 
 
Link:https://gitee.com/openeuler/kernel/pulls/5258

 

Reviewed-by: default avatarKevin Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 6c45e911 be5ee944
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
.. SPDX-License-Identifier: GPL-2.0

===================================================================
CSV Guest API Documentation
===================================================================

1. General description
======================

The CSV guest driver exposes IOCTL interfaces via the /dev/csv-guest misc
device to allow userspace to get certain CSV guest-specific details.

2. API description
==================

In this section, for each supported IOCTL, the following information is
provided along with a generic description.

:Input parameters: Parameters passed to the IOCTL and related details.
:Output: Details about output data and return value (with details about
         the non common error values).

2.1 CSV_CMD_GET_REPORT
-----------------------

:Input parameters: struct csv_report_req
:Output: Upon successful execution, CSV_REPORT data is copied to
         csv_report_req.report_data and return 0. Return -EINVAL for invalid
         operands, -EIO on VMMCALL failure or standard error number on other
         common failures.

The CSV_CMD_GET_REPORT IOCTL can be used by the attestation software to get
the CSV_REPORT from the CSV module using VMMCALL[KVM_HC_VM_ATTESTATION].
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ KVM_X86_OP(complete_emulated_msr)
KVM_X86_OP(vcpu_deliver_sipi_vector)
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
KVM_X86_OP_OPTIONAL(get_untagged_addr)
KVM_X86_OP_OPTIONAL(vm_attestation)

#undef KVM_X86_OP
#undef KVM_X86_OP_OPTIONAL
+5 −0
Original line number Diff line number Diff line
@@ -1771,6 +1771,11 @@ struct kvm_x86_ops {
	unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu);

	gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);

	/*
	 * Attestation interface for HYGON CSV guest
	 */
	int (*vm_attestation)(struct kvm *kvm, unsigned long gpa, unsigned long len);
};

struct kvm_x86_nested_ops {
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ ifdef CONFIG_HYPERV
kvm-amd-y		+= svm/svm_onhyperv.o
endif

kvm-amd-$(CONFIG_HYGON_CSV)	+= svm/csv.o

obj-$(CONFIG_KVM)	+= kvm.o
obj-$(CONFIG_KVM_INTEL)	+= kvm-intel.o
obj-$(CONFIG_KVM_AMD)	+= kvm-amd.o

arch/x86/kvm/svm/csv.c

0 → 100644
+112 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * CSV driver for KVM
 *
 * HYGON CSV support
 *
 * Copyright (C) Hygon Info Technologies Ltd.
 */

#include <linux/kvm_host.h>
#include <linux/psp-sev.h>
#include <linux/psp-hygon.h>
#include <linux/memory.h>
#include <linux/kvm_types.h>
#include <asm/cacheflush.h>
#include "kvm_cache_regs.h"
#include "svm.h"
#include "csv.h"
#include "x86.h"

#undef  pr_fmt
#define pr_fmt(fmt) "CSV: " fmt

/* Function and variable pointers for hooks */
struct hygon_kvm_hooks_table hygon_kvm_hooks;

static struct kvm_x86_ops csv_x86_ops;
static const char csv_vm_mnonce[] = "VM_ATTESTATION";

int csv_vm_attestation(struct kvm *kvm, unsigned long gpa, unsigned long len)
{
	struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
	struct sev_data_attestation_report *data = NULL;
	struct page **pages;
	unsigned long guest_uaddr, n;
	int ret = 0, offset, error;

	if (!sev_guest(kvm) || !hygon_kvm_hooks.sev_hooks_installed)
		return -ENOTTY;

	/*
	 * The physical address of guest must valid and page aligned, and
	 * the length of guest memory region must be page size aligned.
	 */
	if (!gpa || (gpa & ~PAGE_MASK) || (len & ~PAGE_MASK)) {
		pr_err("invalid guest address or length\n");
		return -EFAULT;
	}

	guest_uaddr = gfn_to_hva(kvm, gpa_to_gfn(gpa));
	pages = hygon_kvm_hooks.sev_pin_memory(kvm, guest_uaddr, len, &n, 1);
	if (IS_ERR(pages))
		return PTR_ERR(pages);

	/*
	 * The attestation report must be copied into contiguous memory region,
	 * lets verify that userspace memory pages are contiguous before we
	 * issue commmand.
	 */
	if (hygon_kvm_hooks.get_num_contig_pages(0, pages, n) != n) {
		ret = -EINVAL;
		goto e_unpin_memory;
	}

	ret = -ENOMEM;
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		goto e_unpin_memory;

	/* csv_vm_mnonce indicates attestation request from guest */
	if (sizeof(csv_vm_mnonce) >= sizeof(data->mnonce)) {
		ret = -EINVAL;
		goto e_free;
	}

	memcpy(data->mnonce, csv_vm_mnonce, sizeof(csv_vm_mnonce));

	offset = guest_uaddr & (PAGE_SIZE - 1);
	data->address = __sme_page_pa(pages[0]) + offset;
	data->len = len;

	data->handle = sev->handle;
	ret = hygon_kvm_hooks.sev_issue_cmd(kvm, SEV_CMD_ATTESTATION_REPORT,
					    data, &error);

	if (ret)
		pr_err("vm attestation ret %#x, error %#x\n", ret, error);

e_free:
	kfree(data);
e_unpin_memory:
	hygon_kvm_hooks.sev_unpin_memory(kvm, pages, n);
	return ret;
}

void csv_exit(void)
{
}

void __init csv_init(struct kvm_x86_ops *ops)
{
	/*
	 * Hygon CSV is indicated by X86_FEATURE_SEV, return directly if CSV
	 * is unsupported.
	 */
	if (!boot_cpu_has(X86_FEATURE_SEV))
		return;

	memcpy(&csv_x86_ops, ops, sizeof(struct kvm_x86_ops));

	ops->vm_attestation = csv_vm_attestation;
}
Loading