crypto: ccp - Add GET_ID SEV command
authorJanakarajan Natarajan <Janakarajan.Natarajan@amd.com>
Fri, 25 May 2018 20:23:30 +0000 (15:23 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 30 May 2018 16:13:56 +0000 (00:13 +0800)
The GET_ID command, added as of SEV API v0.16, allows the SEV firmware
to be queried about a unique CPU ID. This unique ID can then be used
to obtain the public certificate containing the Chip Endorsement Key
(CEK) public key signed by the AMD SEV Signing Key (ASK).

For more information please refer to "Section 5.12 GET_ID" of
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Signed-off-by: Janakarajan Natarajan <Janakarajan.Natarajan@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/ccp/psp-dev.c
include/linux/psp-sev.h
include/uapi/linux/psp-sev.h

index 12838b406696e77aef8247f79eed7c726246d0dd..ff478d826d7d351a3184d33df2bb405e28bdf698 100644 (file)
@@ -119,6 +119,7 @@ static int sev_cmd_buffer_len(int cmd)
        case SEV_CMD_RECEIVE_UPDATE_VMSA:       return sizeof(struct sev_data_receive_update_vmsa);
        case SEV_CMD_LAUNCH_UPDATE_SECRET:      return sizeof(struct sev_data_launch_secret);
        case SEV_CMD_DOWNLOAD_FIRMWARE:         return sizeof(struct sev_data_download_firmware);
+       case SEV_CMD_GET_ID:                    return sizeof(struct sev_data_get_id);
        default:                                return 0;
        }
 
@@ -510,6 +511,46 @@ e_free:
        return ret;
 }
 
+static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)
+{
+       struct sev_data_get_id *data;
+       u64 data_size, user_size;
+       void *id_blob, *mem;
+       int ret;
+
+       /* SEV GET_ID available from SEV API v0.16 and up */
+       if (!SEV_VERSION_GREATER_OR_EQUAL(0, 16))
+               return -ENOTSUPP;
+
+       /* SEV FW expects the buffer it fills with the ID to be
+        * 8-byte aligned. Memory allocated should be enough to
+        * hold data structure + alignment padding + memory
+        * where SEV FW writes the ID.
+        */
+       data_size = ALIGN(sizeof(struct sev_data_get_id), 8);
+       user_size = sizeof(struct sev_user_data_get_id);
+
+       mem = kzalloc(data_size + user_size, GFP_KERNEL);
+       if (!mem)
+               return -ENOMEM;
+
+       data = mem;
+       id_blob = mem + data_size;
+
+       data->address = __psp_pa(id_blob);
+       data->len = user_size;
+
+       ret = __sev_do_cmd_locked(SEV_CMD_GET_ID, data, &argp->error);
+       if (!ret) {
+               if (copy_to_user((void __user *)argp->data, id_blob, data->len))
+                       ret = -EFAULT;
+       }
+
+       kfree(mem);
+
+       return ret;
+}
+
 static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)
 {
        struct sev_user_data_pdh_cert_export input;
@@ -647,6 +688,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
        case SEV_PDH_CERT_EXPORT:
                ret = sev_ioctl_do_pdh_export(&input);
                break;
+       case SEV_GET_ID:
+               ret = sev_ioctl_do_get_id(&input);
+               break;
        default:
                ret = -EINVAL;
                goto out;
index 1d24962460725d0c6d0b15967bb51bca23b7ebeb..827c601841c433ba93a88e0c9c5bf0ed48874aa6 100644 (file)
@@ -55,6 +55,7 @@ enum sev_cmd {
        SEV_CMD_PDH_GEN                 = 0x009,
        SEV_CMD_DF_FLUSH                = 0x00A,
        SEV_CMD_DOWNLOAD_FIRMWARE       = 0x00B,
+       SEV_CMD_GET_ID                  = 0x00C,
 
        /* Guest commands */
        SEV_CMD_DECOMMISSION            = 0x020,
@@ -141,6 +142,16 @@ struct sev_data_download_firmware {
        u32 len;                                /* In */
 } __packed;
 
+/**
+ * struct sev_data_get_id - GET_ID command parameters
+ *
+ * @address: physical address of region to place unique CPU ID(s)
+ * @len: len of the region
+ */
+struct sev_data_get_id {
+       u64 address;                            /* In */
+       u32 len;                                /* In/Out */
+} __packed;
 /**
  * struct sev_data_pdh_cert_export - PDH_CERT_EXPORT command parameters
  *
index 9008f31c7eb65c90a487d99d3f371a00ba526f3f..ac8c60bcc83bb797e99d44ef58c585358c4db3e5 100644 (file)
@@ -30,6 +30,7 @@ enum {
        SEV_PDH_GEN,
        SEV_PDH_CERT_EXPORT,
        SEV_PEK_CERT_IMPORT,
+       SEV_GET_ID,
 
        SEV_MAX,
 };
@@ -123,6 +124,17 @@ struct sev_user_data_pdh_cert_export {
        __u32 cert_chain_len;                   /* In/Out */
 } __packed;
 
+/**
+ * struct sev_user_data_get_id - GET_ID command parameters
+ *
+ * @socket1: Buffer to pass unique ID of first socket
+ * @socket2: Buffer to pass unique ID of second socket
+ */
+struct sev_user_data_get_id {
+       __u8 socket1[64];                       /* Out */
+       __u8 socket2[64];                       /* Out */
+} __packed;
+
 /**
  * struct sev_issue_cmd - SEV ioctl parameters
  *