Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions arch/x86/coco/tdx/tdx.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,26 @@ int tdx_mcall_extend_rtmr(u8 index, u8 *data)
}
EXPORT_SYMBOL_GPL(tdx_mcall_extend_rtmr);

/**
* tdx_mcall_key_get() - Wrapper to derive a persistent key for the TD,
* customized to the TD's measurements and policy
* using TDG.MR.KEY.GET TDCALL.
* @indata: Address of the input buffer with TDKEYREQUEST data.
* @outdata: Address of the output buffer with the requested key data.
*
* Return 0 on success or error code on other TDCALL failures.
*/
u64 tdx_mcall_key_get(u8 *indata, u8 *outdata)
{
struct tdx_module_args args = {
.rcx = virt_to_phys(indata),
.rdx = virt_to_phys(outdata),
};

return __tdcall(TDG_MR_KEY_GET, &args);
}
EXPORT_SYMBOL_GPL(tdx_mcall_key_get);

/**
* tdx_hcall_get_quote() - Wrapper to request TD Quote using GetQuote
* hypercall.
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/shared/tdx.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define TDG_MEM_PAGE_ACCEPT 6
#define TDG_VM_RD 7
#define TDG_VM_WR 8
#define TDG_MR_KEY_GET 29

/* TDX attributes */
#define TDX_ATTR_DEBUG_BIT 0
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/tdx.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport);

int tdx_mcall_extend_rtmr(u8 index, u8 *data);

u64 tdx_mcall_key_get(u8 *indata, u8 *outdata);

u64 tdx_hcall_get_quote(u8 *buf, size_t size);

void __init tdx_dump_attributes(u64 td_attr);
Expand Down
50 changes: 50 additions & 0 deletions drivers/virt/coco/tdx-guest/tdx-guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,54 @@ static long tdx_get_report0(struct tdx_report_req __user *req)
USER_SOCKPTR(req->tdreport));
}

static long tdx_key_get(struct tdx_key_get_req __user *req)
{
u8 *indata = NULL, *outdata = NULL;
long ret = 0;
u64 err;

/*
* TDG.MR.KEY.GET expects the TDKEYREQUEST input buffer to be 128B
* aligned and the key output buffer to be 32B aligned. kmalloc()
* guarantees alignment to the allocation size for power-of-two sizes,
* and TDX_TDKEYREQ_LEN (128) and TDX_KEY_LEN (32) are both powers of
* two, so the returned buffers meet the required alignment.
*/
indata = kmalloc(sizeof(req->tdkeyreq), GFP_KERNEL);
if (!indata)
return -ENOMEM;

outdata = kzalloc(sizeof(req->outkey), GFP_KERNEL);
if (!outdata) {
ret = -ENOMEM;
goto out;
}

if (copy_from_user(indata, req->tdkeyreq, sizeof(req->tdkeyreq))) {
ret = -EFAULT;
goto out;
}

/* Get derived key using "TDG.MR.KEY.GET" TDCALL */
err = tdx_mcall_key_get(indata, outdata);
if (err) {
ret = -EIO;
if (copy_to_user(&req->err_code, &err, sizeof(u64)))
ret = -EFAULT;
goto out;
}

/* On success, write back the derived key and clear err_code (0) */
if (copy_to_user(&req->err_code, &err, sizeof(u64)) ||
copy_to_user(&req->outkey, outdata, sizeof(req->outkey)))
ret = -EFAULT;

out:
kfree_sensitive(indata);
kfree_sensitive(outdata);
return ret;
}

static void free_quote_buf(void *buf)
{
size_t len = PAGE_ALIGN(GET_QUOTE_BUF_SIZE);
Expand Down Expand Up @@ -353,6 +401,8 @@ static long tdx_guest_ioctl(struct file *file, unsigned int cmd,
switch (cmd) {
case TDX_CMD_GET_REPORT0:
return tdx_get_report0((struct tdx_report_req __user *)arg);
case TDX_CMD_KEY_GET:
return tdx_key_get((struct tdx_key_get_req __user *)arg);
default:
return -ENOTTY;
}
Expand Down
27 changes: 27 additions & 0 deletions include/uapi/linux/tdx-guest.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
/* Length of TDREPORT used in TDG.MR.REPORT TDCALL */
#define TDX_REPORT_LEN 1024

/* TDKEYREQ struct length */
#define TDX_TDKEYREQ_LEN 128

/* Length of the derived key */
#define TDX_KEY_LEN 32

/**
* struct tdx_report_req - Request struct for TDX_CMD_GET_REPORT0 IOCTL.
*
Expand All @@ -30,6 +36,19 @@ struct tdx_report_req {
__u8 tdreport[TDX_REPORT_LEN];
};

/**
* struct tdx_key_get_req - Request struct for TDX_CMD_KEY_GET IOCTL.
*
* @tdkeyreq: TDKEYREQ struct.
* @outkey: Derived key output
* @err_code: TDG.MR.KEY.GET TDCALL return error code.
*/
struct tdx_key_get_req {
__u8 tdkeyreq[TDX_TDKEYREQ_LEN];
__u8 outkey[TDX_KEY_LEN];
__u64 err_code;
};

/*
* TDX_CMD_GET_REPORT0 - Get TDREPORT0 (a.k.a. TDREPORT subtype 0) using
* TDCALL[TDG.MR.REPORT]
Expand All @@ -39,4 +58,12 @@ struct tdx_report_req {
*/
#define TDX_CMD_GET_REPORT0 _IOWR('T', 1, struct tdx_report_req)

/*
* TDX_CMD_KEY_GET - Request to derive a persistent key for the TD,
* customized to the TD's measurements and policy.
*
* Returns 0 on success, and standard errno on other failures.
*/
#define TDX_CMD_KEY_GET _IOWR('T', 5, struct tdx_key_get_req)

#endif /* _UAPI_LINUX_TDX_GUEST_H_ */
Loading