From 7219ad56a29ac8802427aa3db3158a6fdbd30484 Mon Sep 17 00:00:00 2001 From: fangbaoshun Date: Thu, 22 Sep 2022 10:59:03 +0800 Subject: [PATCH] anolis: crypto: ccp: Implement CSV_HGSC_CERT_IMPORT ioctl command ANBZ: #8562 The CSV_HGSC_CERT_IMPORT command can be used to import hygon general secure cert to the Secure Proccessor, to enable Hygon Secure Functions, such as CSV, TPM, TPCM, TDM. Signed-off-by: fangbaoshun Signed-off-by: hanliyang --- drivers/crypto/ccp/sev-dev.c | 73 +++++++++++++++++++++++++++++++++++- include/linux/psp-sev.h | 21 +++++++++++ include/uapi/linux/psp-sev.h | 24 ++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index f97166fba9d9..35d97452d3e5 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -127,6 +127,15 @@ static int sev_wait_cmd_ioc(struct sev_device *sev, static int sev_cmd_buffer_len(int cmd) { + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { + switch (cmd) { + case CSV_CMD_HGSC_CERT_IMPORT: + return sizeof(struct csv_data_hgsc_cert_import); + default: + break; + } + } + switch (cmd) { case SEV_CMD_INIT: return sizeof(struct sev_data_init); case SEV_CMD_INIT_EX: return sizeof(struct sev_data_init_ex); @@ -1064,6 +1073,50 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) return ret; } +static int csv_ioctl_do_hgsc_import(struct sev_issue_cmd *argp) +{ + struct csv_user_data_hgsc_cert_import input; + struct csv_data_hgsc_cert_import *data; + void *hgscsk_blob, *hgsc_blob; + int ret; + + if (copy_from_user(&input, (void __user *)argp->data, sizeof(input))) + return -EFAULT; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* copy HGSCSK certificate blobs from userspace */ + hgscsk_blob = psp_copy_user_blob(input.hgscsk_cert_address, input.hgscsk_cert_len); + if (IS_ERR(hgscsk_blob)) { + ret = PTR_ERR(hgscsk_blob); + goto e_free; + } + + data->hgscsk_cert_address = __psp_pa(hgscsk_blob); + data->hgscsk_cert_len = input.hgscsk_cert_len; + + /* copy HGSC certificate blobs from userspace */ + hgsc_blob = psp_copy_user_blob(input.hgsc_cert_address, input.hgsc_cert_len); + if (IS_ERR(hgsc_blob)) { + ret = PTR_ERR(hgsc_blob); + goto e_free_hgscsk; + } + + data->hgsc_cert_address = __psp_pa(hgsc_blob); + data->hgsc_cert_len = input.hgsc_cert_len; + + ret = __sev_do_cmd_locked(CSV_CMD_HGSC_CERT_IMPORT, data, &argp->error); + + kfree(hgsc_blob); +e_free_hgscsk: + kfree(hgscsk_blob); +e_free: + kfree(data); + return ret; +} + static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -1080,11 +1133,26 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) if (copy_from_user(&input, argp, sizeof(struct sev_issue_cmd))) return -EFAULT; - if (input.cmd > SEV_MAX) - return -EINVAL; + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { + if (input.cmd > CSV_MAX) + return -EINVAL; + } else { + if (input.cmd > SEV_MAX) + return -EINVAL; + } mutex_lock(&sev_cmd_mutex); + if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { + switch (input.cmd) { + case CSV_HGSC_CERT_IMPORT: + ret = csv_ioctl_do_hgsc_import(&input); + goto result_to_user; + default: + break; + } + } + switch (input.cmd) { case SEV_FACTORY_RESET: @@ -1120,6 +1188,7 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) goto out; } +result_to_user: if (copy_to_user(argp, &input, sizeof(struct sev_issue_cmd))) ret = -EFAULT; out: diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 7fd17e82bab4..2b40efb57274 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -81,6 +81,11 @@ enum sev_cmd { SEV_CMD_MAX, }; +enum csv_cmd { + CSV_CMD_HGSC_CERT_IMPORT = 0x300, + CSV_CMD_MAX, +}; + /** * struct sev_data_init - INIT command parameters * @@ -523,6 +528,22 @@ struct sev_data_attestation_report { u32 len; /* In/Out */ } __packed; +/** + * struct csv_data_hgsc_cert_import - HGSC_CERT_IMPORT command parameters + * + * @hgscsk_cert_address: HGSCSK certificate chain + * @hgscsk_cert_len: len of HGSCSK certificate + * @hgsc_cert_address: HGSC certificate chain + * @hgsc_cert_len: len of HGSC certificate + */ +struct csv_data_hgsc_cert_import { + u64 hgscsk_cert_address; /* In */ + u32 hgscsk_cert_len; /* In */ + u32 reserved; /* In */ + u64 hgsc_cert_address; /* In */ + u32 hgsc_cert_len; /* In */ +} __packed; + #ifdef CONFIG_CRYPTO_DEV_SP_PSP /** diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index 1c9da485318f..ae76776c0b15 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -32,6 +32,15 @@ enum { SEV_MAX, }; +/** + * CSV platform commands + */ +enum { + CSV_HGSC_CERT_IMPORT = 201, + + CSV_MAX, +}; + /** * SEV Firmware status code */ @@ -154,6 +163,21 @@ struct sev_user_data_get_id2 { __u32 length; /* In/Out */ } __packed; +/** + * struct csv_user_data_hgsc_cert_import - HGSC_CERT_IMPORT command parameters + * + * @hgscsk_cert_address: HGSCSK certificate chain + * @hgscsk_cert_len: length of HGSCSK certificate + * @hgsc_cert_address: HGSC certificate chain + * @hgsc_cert_len: length of HGSC certificate + */ +struct csv_user_data_hgsc_cert_import { + __u64 hgscsk_cert_address; /* In */ + __u32 hgscsk_cert_len; /* In */ + __u64 hgsc_cert_address; /* In */ + __u32 hgsc_cert_len; /* In */ +} __packed; + /** * struct sev_issue_cmd - SEV ioctl parameters * -- Gitee