Received: by 2002:a05:6602:18e:0:0:0:0 with SMTP id m14csp2437095ioo; Sat, 28 May 2022 13:39:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyEwnuVPKlB46IvtyL0bPSDZ1wh+ZM6WqNlzhOjImjQeuigR2YvFbG7DEj9XJHbT5wwm64T X-Received: by 2002:a17:902:7e01:b0:15e:caea:d6 with SMTP id b1-20020a1709027e0100b0015ecaea00d6mr49216376plm.33.1653770374354; Sat, 28 May 2022 13:39:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1653770374; cv=none; d=google.com; s=arc-20160816; b=mYZVZBC5wgQX+m+U4RizTJ3FLe5rdFYSlW4cJ8tBmuMOxvub1E2CMvYfhaJG+KX77S 0iPovzomlIzIJUsDiqY1bAbRR9XR3XPS1uQus4mXt8zDCiWCVzzm+6n+X8L6SXjObjXw B4+ZhTqYd6xnl3IiujliwOzTVOLw8k/+w16t+nX1FnFsAcfnZyHkJrNftiDueIw5CGrm iY2+rbKqOpa36ns0jhQjzjEXKaraRgJA9vFn1UPxzAk3WS1dd5evk5Rt7H+Mv8lPOln6 HFDyFDrTCqEkPmjbDFdrIAE2JmpmPOxvL9cqJRnXy+nkkRVbJftIL9KwfRbJ7Co6Qy79 DXyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:date:cc:to:from:subject :message-id:dkim-signature; bh=ccBk5+8NcxPyx8hpir71sdG5vlDgaPDNloEPbjmStjc=; b=PqQ/f4FQ6Jg4XxbSUlAa2PXMcjtRyXyfWw60ioTvXagHxAOl4AaD2yzPmU8rj//YOt dBXjVZsAhWKAhLC5H+2r9xeXGpgeSuxf+RIRoL3gawaM34K4u2ZewKmo5GBmRhqIWHBm dAnDfW4CKh1YLrbU+s0uWOT88ix8GbxEO1dL4uCh34qO4I5+FsjxF312VI5BHfHjlAjd Uz2Mc6zGDC9J0NfYKNAylho/QEOgevyVu3fs66QZU0bTKZQihWEq1Us/0aionzqNgebb LyXOD/w0Y88l6kl8QcPui2Ag6VIyHZor3k+MveNKGJUWT/F6jk4GhkXrdTomxrJ5UjGU COxA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=PolJLCZ1; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id d20-20020a170902b71400b00158d1f2d451si5457906pls.45.2022.05.28.13.39.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 May 2022 13:39:34 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=PolJLCZ1; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2660561620; Sat, 28 May 2022 12:41:41 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352704AbiE0Lzh (ORCPT + 99 others); Fri, 27 May 2022 07:55:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41024 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352786AbiE0Luv (ORCPT ); Fri, 27 May 2022 07:50:51 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0409132741 for ; Fri, 27 May 2022 04:45:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1653651918; x=1685187918; h=message-id:subject:from:to:cc:date:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ku6DON7XdpvGJoLwbB79r2uuBcp/VCl2MGDwRymTj14=; b=PolJLCZ1nCig/j3RiufAnZVDVWDZsUqhfCZsS9HP/PvmfbGJSjthLVwB U3ro7FxLihJl/7N+2f9Hk7C0UECiL4FHpBt3/6N+Y5DRla3/4QkJHPccm +O3336KQw+YZWhKpmF/MSjH06FZxEqFUYMbYOb+1dCGQHp8PuyiayJedi BhGrtqB5YmenkgihGnUbWNRCz/jSV6Nicu3oiwgzM9dQn0mNMcLQ2mzbi mJj9SKqMkxwfT+n4UHLsOjOF2hMyvpxAV1bspWgxF5kpw8fZoEDrYQe0i X2+dYH3z8nMpXMy3va7Q0xZiftU1dFANdFJnw+7wDVPKGKc/fgoFyQ48H Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10359"; a="274186151" X-IronPort-AV: E=Sophos;i="5.91,255,1647327600"; d="scan'208";a="274186151" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2022 04:45:18 -0700 X-IronPort-AV: E=Sophos;i="5.91,255,1647327600"; d="scan'208";a="603835273" Received: from jtongex-mobl.amr.corp.intel.com (HELO khuang2-desk.gar.corp.intel.com) ([10.254.35.135]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2022 04:45:14 -0700 Message-ID: Subject: Re: [PATCH v7 1/5] x86/tdx: Add TDX Guest attestation interface driver From: Kai Huang To: Kuppuswamy Sathyanarayanan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org Cc: "H . Peter Anvin" , "Kirill A . Shutemov" , Tony Luck , Andi Kleen , Wander Lairson Costa , Isaku Yamahata , marcelo.cerri@canonical.com, tim.gardner@canonical.com, khalid.elmously@canonical.com, philip.cox@canonical.com, linux-kernel@vger.kernel.org Date: Fri, 27 May 2022 23:45:12 +1200 In-Reply-To: <20220524040517.703581-2-sathyanarayanan.kuppuswamy@linux.intel.com> References: <20220524040517.703581-1-sathyanarayanan.kuppuswamy@linux.intel.com> <20220524040517.703581-2-sathyanarayanan.kuppuswamy@linux.intel.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.42.4 (3.42.4-2.fc35) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 2022-05-23 at 21:05 -0700, Kuppuswamy Sathyanarayanan wrote: > In TDX guest, attestation is used to verify the trustworthiness of a TD > to other entities before provisioning secrets to the TD. > > One usage example is, when a TD guest uses encrypted drive and if the > decryption keys required to access the drive are stored in a secure 3rd > party keyserver, the key server can use attestation to verify TD's > trustworthiness and release the decryption keys to the TD. > > The attestation process consists of two steps: TDREPORT generation and > Quote generation. > > TDREPORT (TDREPORT_STRUCT) is a fixed-size data structure generated by > the TDX module which contains TD-specific information (such as TD > measurements), platform security version, and the MAC to protect the > integrity of the TDREPORT. The TD kernel uses TDCALL[TDG.MR.REPORT] to > get the TDREPORT from the TDX module. A user-provided 64-Byte > REPORTDATA is used as input and included in the TDREPORT. Typically it > can be some nonce provided by attestation service so the TDREPORT can > be verified uniquely. More details about TDREPORT can be found in > Intel TDX Module specification, section titled "TDG.MR.REPORT Leaf". > > TDREPORT can only be verified on local platform as the MAC key is bound > to the platform. To support remote verification of the TDREPORT, TDX > leverages Intel SGX Quote Enclave (QE) to verify the TDREPORT locally > and convert it to a remote verifiable Quote. > > After getting the TDREPORT, the second step of the attestation process > is to send it to the QE to generate the Quote. TDX doesn't support SGX > inside the TD, so the QE can be deployed in the host, or in another > legacy VM with SGX support. How to send the TDREPORT to QE and receive > the Quote is implementation and deployment specific. > > Implement a basic attestation driver to allow TD userspace to get the > TDREPORT. The TD userspace attestation software can get the TDREPORT > and then choose whatever communication channel available (i.e. vsock) > to send the TDREPORT to QE and receive the Quote. > > Also note that explicit access permissions are not enforced in this > driver because the quote and measurements are not a secret. However > the access permissions of the device node can be used to set any > desired access policy. The udev default is usually root access > only. > > Operations like getting TDREPORT or Quote generation involves sending > a blob of data as input and getting another blob of data as output. It > was considered to use a sysfs interface for this, but it doesn't fit > well into the standard sysfs model for configuring values. It would be > possible to do read/write on files, but it would need multiple file > descriptors, which would be somewhat messy. IOCTLs seems to be the best > fitting and simplest model for this use case. Also, the REPORTDATA used > in TDREPORT generation can possibly come from attestation service to > uniquely verify the Quote (like per instance verification). In such > case, since REPORTDATA is a secret, using sysfs to share it is insecure > compared to sending it via IOCTL. Acked-by: Kai Huang > > Reviewed-by: Tony Luck > Reviewed-by: Andi Kleen > Acked-by: Kirill A. Shutemov > Signed-off-by: Kuppuswamy Sathyanarayanan > --- > arch/x86/coco/tdx/Makefile | 2 +- > arch/x86/coco/tdx/attest.c | 118 ++++++++++++++++++++++++++++++++ > arch/x86/include/uapi/asm/tdx.h | 42 ++++++++++++ > 3 files changed, 161 insertions(+), 1 deletion(-) > create mode 100644 arch/x86/coco/tdx/attest.c > create mode 100644 arch/x86/include/uapi/asm/tdx.h > > diff --git a/arch/x86/coco/tdx/Makefile b/arch/x86/coco/tdx/Makefile > index 46c55998557d..d2db3e6770e5 100644 > --- a/arch/x86/coco/tdx/Makefile > +++ b/arch/x86/coco/tdx/Makefile > @@ -1,3 +1,3 @@ > # SPDX-License-Identifier: GPL-2.0 > > -obj-y += tdx.o tdcall.o > +obj-y += tdx.o tdcall.o attest.o > diff --git a/arch/x86/coco/tdx/attest.c b/arch/x86/coco/tdx/attest.c > new file mode 100644 > index 000000000000..24db0bad4923 > --- /dev/null > +++ b/arch/x86/coco/tdx/attest.c > @@ -0,0 +1,118 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * attest.c - TDX guest attestation interface driver. > + * > + * Implements user interface to trigger attestation process. > + * > + * Copyright (C) 2022 Intel Corporation > + * > + */ > + > +#define pr_fmt(fmt) "x86/tdx: attest: " fmt > + > +#include > +#include > +#include > +#include > +#include > + > +#define DRIVER_NAME "tdx-attest" > + > +/* TDREPORT module call leaf ID */ > +#define TDX_GET_REPORT 4 > + > +static struct miscdevice miscdev; > + > +static long tdx_get_report(void __user *argp) > +{ > + void *reportdata = NULL, *tdreport = NULL; > + long ret; > + > + /* Allocate buffer space for REPORTDATA */ > + reportdata = kmalloc(TDX_REPORTDATA_LEN, GFP_KERNEL); > + if (!reportdata) > + return -ENOMEM; > + > + /* Allocate buffer space for TDREPORT */ > + tdreport = kmalloc(TDX_REPORT_LEN, GFP_KERNEL); > + if (!tdreport) { > + ret = -ENOMEM; > + goto out; > + } > + > + /* Copy REPORTDATA from the user buffer */ > + if (copy_from_user(reportdata, argp, TDX_REPORTDATA_LEN)) { > + ret = -EFAULT; > + goto out; > + } > + > + /* > + * Generate TDREPORT using "TDG.MR.REPORT" TDCALL. > + * > + * Get the TDREPORT using REPORTDATA as input. Refer to > + * section 22.3.3 TDG.MR.REPORT leaf in the TDX Module 1.0 > + * Specification for detailed information. > + */ > + ret = __tdx_module_call(TDX_GET_REPORT, virt_to_phys(tdreport), > + virt_to_phys(reportdata), 0, 0, NULL); > + if (ret) { > + pr_debug("TDREPORT TDCALL failed, status:%lx\n", ret); > + ret = -EIO; > + goto out; > + } > + > + /* Copy TDREPORT back to the user buffer */ > + if (copy_to_user(argp, tdreport, TDX_REPORT_LEN)) > + ret = -EFAULT; > + > +out: > + kfree(reportdata); > + kfree(tdreport); > + return ret; > +} > + > +static long tdx_attest_ioctl(struct file *file, unsigned int cmd, > + unsigned long arg) > +{ > + void __user *argp = (void __user *)arg; > + long ret = -EINVAL; > + > + switch (cmd) { > + case TDX_CMD_GET_REPORT: > + ret = tdx_get_report(argp); > + break; > + default: > + pr_debug("cmd %d not supported\n", cmd); > + break; > + } > + > + return ret; > +} > + > +static const struct file_operations tdx_attest_fops = { > + .owner = THIS_MODULE, > + .unlocked_ioctl = tdx_attest_ioctl, > + .llseek = no_llseek, > +}; > + > +static int __init tdx_attestation_init(void) > +{ > + int ret; > + > + /* Make sure we are in a valid TDX platform */ > + if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) > + return -EIO; > + > + miscdev.name = DRIVER_NAME; > + miscdev.minor = MISC_DYNAMIC_MINOR; > + miscdev.fops = &tdx_attest_fops; > + > + ret = misc_register(&miscdev); > + if (ret) { > + pr_err("misc device registration failed\n"); > + return ret; > + } > + > + return 0; > +} > +device_initcall(tdx_attestation_init) > diff --git a/arch/x86/include/uapi/asm/tdx.h b/arch/x86/include/uapi/asm/tdx.h > new file mode 100644 > index 000000000000..8b57dea67eab > --- /dev/null > +++ b/arch/x86/include/uapi/asm/tdx.h > @@ -0,0 +1,42 @@ > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ > +#ifndef _UAPI_ASM_X86_TDX_H > +#define _UAPI_ASM_X86_TDX_H > + > +#include > +#include > + > +/* Length of the REPORTDATA used in TDG.MR.REPORT TDCALL */ > +#define TDX_REPORTDATA_LEN 64 > + > +/* Length of TDREPORT used in TDG.MR.REPORT TDCALL */ > +#define TDX_REPORT_LEN 1024 > + > +/** > + * struct tdx_report_req: Get TDREPORT using REPORTDATA as input. > + * > + * @reportdata : User-defined 64-Byte REPORTDATA to be included into > + * TDREPORT. Typically it can be some nonce provided by > + * attestation service, so the generated TDREPORT can be > + * uniquely verified. > + * @tdreport : TDREPORT output from TDCALL[TDG.MR.REPORT] of size > + * TDX_REPORT_LEN. > + * > + * Used in TDX_CMD_GET_REPORT IOCTL request. > + */ > +struct tdx_report_req { > + union { > + __u8 reportdata[TDX_REPORTDATA_LEN]; > + __u8 tdreport[TDX_REPORT_LEN]; > + }; > +}; > + > +/* > + * TDX_CMD_GET_REPORT - Get TDREPORT using TDCALL[TDG.MR.REPORT] > + * > + * Return 0 on success, -EIO on TDCALL execution failure, and > + * standard errno on other general error cases. > + * > + */ > +#define TDX_CMD_GET_REPORT _IOWR('T', 0x01, struct tdx_report_req) > + > +#endif /* _UAPI_ASM_X86_TDX_H */