diff mbox series

qapi, target/i386/sev: Add cpu0-id to query-sev-capabilities

Message ID 20220221160850.1484364-1-dovmurik@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series qapi, target/i386/sev: Add cpu0-id to query-sev-capabilities | expand

Commit Message

Dov Murik Feb. 21, 2022, 4:08 p.m. UTC
Add a new field 'cpu0-id' to the response of query-sev-capabilities
QMP command.  The value of the field is the hex-encoded 64-byte unique
ID of the CPU0 (socket 0), which can be used to retrieve the signed CEK
of the CPU from AMD's Key Distribution Service (KDS).

Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
---
 qapi/misc-target.json |  4 ++++
 target/i386/sev.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

Comments

Daniel P. Berrangé Feb. 21, 2022, 4:24 p.m. UTC | #1
On Mon, Feb 21, 2022 at 04:08:50PM +0000, Dov Murik wrote:
> Add a new field 'cpu0-id' to the response of query-sev-capabilities
> QMP command.  The value of the field is the hex-encoded 64-byte unique
> ID of the CPU0 (socket 0), which can be used to retrieve the signed CEK
> of the CPU from AMD's Key Distribution Service (KDS).
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> ---
>  qapi/misc-target.json |  4 ++++
>  target/i386/sev.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+)
> 
> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> index 4bc45d2474..d9b4991c86 100644
> --- a/qapi/misc-target.json
> +++ b/qapi/misc-target.json
> @@ -177,6 +177,8 @@
>  #
>  # @cert-chain:  PDH certificate chain (base64 encoded)
>  #
> +# @cpu0-id: 64-byte unique ID of CPU0 (hex encoded) (since 7.0)

For binary data in QAPI we've pretty much standardized on using
base64 encoding. I think we should stick with that encoding.

> +#
>  # @cbitpos: C-bit location in page table entry
>  #
>  # @reduced-phys-bits: Number of physical Address bit reduction when SEV is
> @@ -187,6 +189,7 @@
>  { 'struct': 'SevCapability',
>    'data': { 'pdh': 'str',
>              'cert-chain': 'str',
> +            'cpu0-id': 'str',
>              'cbitpos': 'int',
>              'reduced-phys-bits': 'int'},
>    'if': 'TARGET_I386' }
> @@ -205,6 +208,7 @@
>  #
>  # -> { "execute": "query-sev-capabilities" }
>  # <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
> +#                  "cpu0-id": "5ea2e1...90ea39",
>  #                  "cbitpos": 47, "reduced-phys-bits": 5}}
>  #
>  ##

Regards,
Daniel
Dov Murik Feb. 21, 2022, 5:49 p.m. UTC | #2
Thanks Daniel for reviewing.


On 21/02/2022 18:24, Daniel P. Berrangé wrote:
> On Mon, Feb 21, 2022 at 04:08:50PM +0000, Dov Murik wrote:
>> Add a new field 'cpu0-id' to the response of query-sev-capabilities
>> QMP command.  The value of the field is the hex-encoded 64-byte unique
>> ID of the CPU0 (socket 0), which can be used to retrieve the signed CEK
>> of the CPU from AMD's Key Distribution Service (KDS).
>>
>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
>> ---
>>  qapi/misc-target.json |  4 ++++
>>  target/i386/sev.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 47 insertions(+)
>>
>> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
>> index 4bc45d2474..d9b4991c86 100644
>> --- a/qapi/misc-target.json
>> +++ b/qapi/misc-target.json
>> @@ -177,6 +177,8 @@
>>  #
>>  # @cert-chain:  PDH certificate chain (base64 encoded)
>>  #
>> +# @cpu0-id: 64-byte unique ID of CPU0 (hex encoded) (since 7.0)
> 
> For binary data in QAPI we've pretty much standardized on using
> base64 encoding. I think we should stick with that encoding.
> 

OK, I'll change that to base64.

I thought about the cpu0-id as some kind of "address string", like mac
addresses or IPv6 addresses which are usually represented as hex strings
and not as base64-encoded.  But I guess that the AMD CPU unique ID
doesn't have the same legacy (and accepted notation) as mac addresses or
IPv6 addresses, so we might as well treat it as "regular" binary data.

Going with base64 also saves some code because QEMU doesn't have a
ready-made hex_encode() function (I copied mine from a static function
in crypto/hash.c).

-Dov


>> +#
>>  # @cbitpos: C-bit location in page table entry
>>  #
>>  # @reduced-phys-bits: Number of physical Address bit reduction when SEV is
>> @@ -187,6 +189,7 @@
>>  { 'struct': 'SevCapability',
>>    'data': { 'pdh': 'str',
>>              'cert-chain': 'str',
>> +            'cpu0-id': 'str',
>>              'cbitpos': 'int',
>>              'reduced-phys-bits': 'int'},
>>    'if': 'TARGET_I386' }
>> @@ -205,6 +208,7 @@
>>  #
>>  # -> { "execute": "query-sev-capabilities" }
>>  # <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
>> +#                  "cpu0-id": "5ea2e1...90ea39",
>>  #                  "cbitpos": 47, "reduced-phys-bits": 5}}
>>  #
>>  ##
> 
> Regards,
> Daniel
diff mbox series

Patch

diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 4bc45d2474..d9b4991c86 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -177,6 +177,8 @@ 
 #
 # @cert-chain:  PDH certificate chain (base64 encoded)
 #
+# @cpu0-id: 64-byte unique ID of CPU0 (hex encoded) (since 7.0)
+#
 # @cbitpos: C-bit location in page table entry
 #
 # @reduced-phys-bits: Number of physical Address bit reduction when SEV is
@@ -187,6 +189,7 @@ 
 { 'struct': 'SevCapability',
   'data': { 'pdh': 'str',
             'cert-chain': 'str',
+            'cpu0-id': 'str',
             'cbitpos': 'int',
             'reduced-phys-bits': 'int'},
   'if': 'TARGET_I386' }
@@ -205,6 +208,7 @@ 
 #
 # -> { "execute": "query-sev-capabilities" }
 # <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE",
+#                  "cpu0-id": "5ea2e1...90ea39",
 #                  "cbitpos": 47, "reduced-phys-bits": 5}}
 #
 ##
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 025ff7a6f8..c87c69b2f3 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -82,6 +82,8 @@  struct SevGuestState {
 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
 #define DEFAULT_SEV_DEVICE      "/dev/sev"
 
+#define SEV_UNIQUE_ID_LEN       64
+
 #define SEV_INFO_BLOCK_GUID     "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
 typedef struct __attribute__((__packed__)) SevInfoBlock {
     /* SEV-ES Reset Vector Address */
@@ -531,11 +533,47 @@  e_free:
     return 1;
 }
 
+static int
+sev_get_id(int fd, guchar *id_buf, size_t id_buf_len, Error **errp)
+{
+    struct sev_user_data_get_id2 id = {
+        .address = (unsigned long)id_buf,
+        .length = id_buf_len
+    };
+    int err, r;
+
+    r = sev_platform_ioctl(fd, SEV_GET_ID2, &id, &err);
+    if (r < 0) {
+        error_setg(errp, "SEV: Failed to get ID ret=%d fw_err=%d (%s)",
+                   r, err, fw_error_to_str(err));
+        return 1;
+    }
+
+    return 0;
+}
+
+static const char hex[] = "0123456789abcdef";
+
+static gchar *hex_encode(guchar *buf, size_t len)
+{
+    gchar *str = g_new0(gchar, (len * 2) + 1);
+    size_t i;
+
+    for (i = 0; i < len; i++) {
+        str[(i * 2)] = hex[(buf[i] >> 4) & 0xf];
+        str[(i * 2) + 1] = hex[buf[i] & 0xf];
+    }
+    str[len * 2] = '\0';
+
+    return str;
+}
+
 static SevCapability *sev_get_capabilities(Error **errp)
 {
     SevCapability *cap = NULL;
     guchar *pdh_data = NULL;
     guchar *cert_chain_data = NULL;
+    guchar cpu0_id[SEV_UNIQUE_ID_LEN];
     size_t pdh_len = 0, cert_chain_len = 0;
     uint32_t ebx;
     int fd;
@@ -561,9 +599,14 @@  static SevCapability *sev_get_capabilities(Error **errp)
         goto out;
     }
 
+    if (sev_get_id(fd, cpu0_id, sizeof(cpu0_id), errp)) {
+        goto out;
+    }
+
     cap = g_new0(SevCapability, 1);
     cap->pdh = g_base64_encode(pdh_data, pdh_len);
     cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
+    cap->cpu0_id = hex_encode(cpu0_id, sizeof(cpu0_id));
 
     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
     cap->cbitpos = ebx & 0x3f;