Message ID | 4ebf6b5c5676718f115e29c9fd34bc11f0c3a799.1648664666.git.sathyanarayanan.kuppuswamy@intel.com (mailing list archive) |
---|---|
State | Deferred, archived |
Headers | show |
Series | Add TDX Guest Attestation support | expand |
On 2022/3/31 上午6:18, Kuppuswamy Sathyanarayanan wrote: > Attestation is the process used by two un-trusted entities to prove to > each other that it can be trusted. In TDX guest, attestation is mainly > used to verify the trustworthiness of a TD to the 3rd party key > servers. > > First step in the attestation process is to generate the TDREPORT data. > This support is added using tdx_mcall_tdreport() API. The second stage > in the attestation process is for the guest to request the VMM generate > and sign a quote based on the TDREPORT acquired earlier. More details > about the steps involved in attestation process can be found in TDX > Guest-Host Communication Interface (GHCI) for Intel TDX 1.5, section > titled "TD attestation" > > Add tdx_hcall_get_quote() helper function to implement the GetQuote > hypercall. > > More details about the GetQuote TDVMCALL are in the Guest-Host > Communication Interface (GHCI) Specification, sec 3.3, titled > "VP.VMCALL<GetQuote>". > > This will be used by the TD attestation driver in follow-on patches. > > Reviewed-by: Tony Luck <tony.luck@intel.com> > Reviewed-by: Andi Kleen <ak@linux.intel.com> > Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> > --- > arch/x86/coco/tdx/tdx.c | 47 ++++++++++++++++++++++++++++++++++++++ > arch/x86/include/asm/tdx.h | 2 ++ > 2 files changed, 49 insertions(+) > > diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c > index 3721e357262e..54b54e321c63 100644 > --- a/arch/x86/coco/tdx/tdx.c > +++ b/arch/x86/coco/tdx/tdx.c > @@ -21,6 +21,7 @@ > > /* TDX hypercall Leaf IDs */ > #define TDVMCALL_MAP_GPA 0x10001 > +#define TDVMCALL_GET_QUOTE 0x10002 > > /* MMIO direction */ > #define EPT_READ 0 > @@ -42,6 +43,10 @@ > #define TDCALL_INVALID_OPERAND 0x8000000000000000 > #define TDCALL_OPERAND_BUSY 0x8000020000000000 > > +/* TDX hypercall error codes */ > +#define TDVMCALL_GET_QUOTE_ERR 0x8000000000000000 > +#define TDVMCALL_GET_QUOTE_QGS_UNAVIL 0x8000000000000001 > + > /* > * Wrapper for standard use of __tdx_hypercall with no output aside from > * return code. > @@ -151,6 +156,48 @@ int tdx_mcall_tdreport(void *data, void *reportdata) > } > EXPORT_SYMBOL_GPL(tdx_mcall_tdreport); > > +/* > + * tdx_hcall_get_quote() - Generate TDQUOTE using TDREPORT_STRUCT. > + * > + * @data : Address of 8KB GPA memory which contains > + * TDREPORT_STRUCT. > + * @len : Length of the GPA in bytes. > + * > + * return 0 on success or failure error number. > + */ > +int tdx_hcall_get_quote(void *data, u64 len) > +{ > + u64 ret; > + > + /* > + * Use confidential guest TDX check to ensure this API is only > + * used by TDX guest platforms. > + */ > + if (!data || !cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) > + return -EINVAL; > + > + /* > + * Pass the physical address of tdreport data to the VMM > + * and trigger the tdquote generation. Quote data will be > + * stored back in the same physical address space. More info > + * about ABI can be found in TDX Guest-Host-Communication > + * Interface (GHCI), sec titled "TDG.VP.VMCALL<GetQuote>". > + */ > + ret = _tdx_hypercall(TDVMCALL_GET_QUOTE, cc_mkdec(virt_to_phys(data)), > + len, 0, 0); May I know why we need cc_mkdec() here? IIUC, this guest physical address(GPA) is stored in the register when TDCALL brings the context back to the VMX root mode, and hypervisor(QEMU) will find the mapped host virtual address(HVA) with the GPA in the register, and the subsequent ops will be HVA<->HVA in hypervisor, EPT will not be involved so no need to cc_mkdec() this GPA. Thanks, -Aubrey
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 3721e357262e..54b54e321c63 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -21,6 +21,7 @@ /* TDX hypercall Leaf IDs */ #define TDVMCALL_MAP_GPA 0x10001 +#define TDVMCALL_GET_QUOTE 0x10002 /* MMIO direction */ #define EPT_READ 0 @@ -42,6 +43,10 @@ #define TDCALL_INVALID_OPERAND 0x8000000000000000 #define TDCALL_OPERAND_BUSY 0x8000020000000000 +/* TDX hypercall error codes */ +#define TDVMCALL_GET_QUOTE_ERR 0x8000000000000000 +#define TDVMCALL_GET_QUOTE_QGS_UNAVIL 0x8000000000000001 + /* * Wrapper for standard use of __tdx_hypercall with no output aside from * return code. @@ -151,6 +156,48 @@ int tdx_mcall_tdreport(void *data, void *reportdata) } EXPORT_SYMBOL_GPL(tdx_mcall_tdreport); +/* + * tdx_hcall_get_quote() - Generate TDQUOTE using TDREPORT_STRUCT. + * + * @data : Address of 8KB GPA memory which contains + * TDREPORT_STRUCT. + * @len : Length of the GPA in bytes. + * + * return 0 on success or failure error number. + */ +int tdx_hcall_get_quote(void *data, u64 len) +{ + u64 ret; + + /* + * Use confidential guest TDX check to ensure this API is only + * used by TDX guest platforms. + */ + if (!data || !cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) + return -EINVAL; + + /* + * Pass the physical address of tdreport data to the VMM + * and trigger the tdquote generation. Quote data will be + * stored back in the same physical address space. More info + * about ABI can be found in TDX Guest-Host-Communication + * Interface (GHCI), sec titled "TDG.VP.VMCALL<GetQuote>". + */ + ret = _tdx_hypercall(TDVMCALL_GET_QUOTE, cc_mkdec(virt_to_phys(data)), + len, 0, 0); + + if (ret) { + if (ret == TDVMCALL_GET_QUOTE_ERR) + return -EINVAL; + else if (ret == TDVMCALL_GET_QUOTE_QGS_UNAVIL) + return -EBUSY; + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tdx_hcall_get_quote); + static u64 get_cc_mask(void) { struct tdx_module_output out; diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 343fd8b17e66..23c5023704a3 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -68,6 +68,8 @@ bool tdx_early_handle_ve(struct pt_regs *regs); int tdx_mcall_tdreport(void *data, void *reportdata); +int tdx_hcall_get_quote(void *data, u64 len); + #else static inline void tdx_early_init(void) { };