qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
@ 2021-11-01 10:21 Dov Murik
  2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
                   ` (3 more replies)
  0 siblings, 4 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-01 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, Dr. David Alan Gilbert,
	Dov Murik, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

Tom Lendacky and Brijesh Singh reported two issues with launching SEV
guests with the -kernel QEMU option when an old [1] or wrongly configured [2]
OVMF images are used.

The fixes in patches 1 and 2 allow such guests to boot by skipping the
kernel/initrd/cmdline hashes addition to the initial guest memory (and
warning the user).

Patch 3 is a refactoring of parts of the same function
sev_add_kernel_loader_hashes() to calculate all padding sizes at
compile-time.  This patch is not required to fix the issues above, but
is suggested as an improvement (no functional change intended).

Note that launch measurement security is not harmed by these fixes: a
Guest Owner that wants to use measured Linux boot with -kernel, must use
(and measure) an OVMF image that designates a proper hashes table area,
and that verifies those hashes when loading the binaries from QEMU via
fw_cfg.

The old OVMFs which don't publish the hashes table GUID or don't reserve
a valid area for it in MEMFD cannot support these hashes verification in
any case (for measured boot with -kernel).


[1] https://lore.kernel.org/qemu-devel/3b9d10d9-5d9c-da52-f18c-cd93c1931706@amd.com/
[2] https://lore.kernel.org/qemu-devel/001dd81a-282d-c307-a657-e228480d4af3@amd.com/

Dov Murik (3):
  sev/i386: Allow launching with -kernel if no OVMF hashes table found
  sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  sev/i386: Perform padding calculations at compile-time

 target/i386/sev.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)


base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e
-- 
2.25.1



^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-01 10:21 [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Dov Murik
@ 2021-11-01 10:21 ` Dov Murik
  2021-11-01 14:25   ` Tom Lendacky
  2021-11-03 16:02   ` Daniel P. Berrangé
  2021-11-01 10:21 ` [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area Dov Murik
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-01 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, Dr. David Alan Gilbert,
	Dov Murik, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
for measured linux boot", 2021-09-30) introduced measured direct boot
with -kernel, using an OVMF-designated hashes table which QEMU fills.

However, if OVMF doesn't designate such an area, QEMU would completely
abort the VM launch.  This breaks launching with -kernel using older
OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.

Instead, just warn the user that -kernel was supplied by OVMF doesn't
specify the GUID for the hashes table.  The following warning will be
displayed during VM launch:

    qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid

Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 target/i386/sev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/i386/sev.c b/target/i386/sev.c
index eede07f11d..682b8ccf6c 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
     int aligned_len;
 
     if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
-        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
+        warn_report("SEV: kernel specified but OVMF has no hash table guid");
         return false;
     }
     area = (SevHashTableDescriptor *)data;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-01 10:21 [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Dov Murik
  2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
@ 2021-11-01 10:21 ` Dov Murik
  2021-11-02 12:36   ` Dr. David Alan Gilbert
  2021-11-03 16:07   ` Daniel P. Berrangé
  2021-11-01 10:21 ` [PATCH 3/3] sev/i386: Perform padding calculations at compile-time Dov Murik
  2021-11-02 10:52 ` [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Brijesh Singh
  3 siblings, 2 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-01 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, Dr. David Alan Gilbert,
	Dov Murik, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
for measured linux boot", 2021-09-30) introduced measured direct boot
with -kernel, using an OVMF-designated hashes table which QEMU fills.

However, no checks are performed on the validity of the hashes area
designated by OVMF.  Specifically, if OVMF publishes the
SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
cause QEMU to write the hashes entries over the first page of the
guest's memory (GPA 0).

Add validity checks to the published area.  If the hashes table area's
base address is zero, or its size is too small to fit the aligned hashes
table, warn and skip the hashes entries addition.  In such case, the
following warning will be displayed:

    qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)

Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
Reported-by: Brijesh Singh <brijesh.singh@amd.com>
---
 target/i386/sev.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/i386/sev.c b/target/i386/sev.c
index 682b8ccf6c..a20ddb545e 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
     uint8_t kernel_hash[HASH_SIZE];
     uint8_t *hashp;
     size_t hash_len = HASH_SIZE;
-    int aligned_len;
+    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
 
     if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
         warn_report("SEV: kernel specified but OVMF has no hash table guid");
         return false;
     }
     area = (SevHashTableDescriptor *)data;
+    if (!area->base || area->size < aligned_len) {
+        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
+                    area->base, area->size);
+        return false;
+    }
 
     /*
      * Calculate hash of kernel command-line with the terminating null byte. If
@@ -1266,7 +1271,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
     memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
 
     /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
-    aligned_len = ROUND_UP(ht->len, 16);
     if (aligned_len != ht->len) {
         /* zero the excess data so the measurement can be reliably calculated */
         memset(ht->padding, 0, aligned_len - ht->len);
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 3/3] sev/i386: Perform padding calculations at compile-time
  2021-11-01 10:21 [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Dov Murik
  2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
  2021-11-01 10:21 ` [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area Dov Murik
@ 2021-11-01 10:21 ` Dov Murik
  2021-11-02 11:36   ` Dr. David Alan Gilbert
  2021-11-03 14:49   ` Philippe Mathieu-Daudé
  2021-11-02 10:52 ` [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Brijesh Singh
  3 siblings, 2 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-01 10:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, Dr. David Alan Gilbert,
	Dov Murik, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

In sev_add_kernel_loader_hashes, the sizes of structs are known at
compile-time, so calculate needed padding at compile-time.

No functional change intended.

Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
---
 target/i386/sev.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/target/i386/sev.c b/target/i386/sev.c
index a20ddb545e..c09de9c6f0 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -109,9 +109,19 @@ typedef struct QEMU_PACKED SevHashTable {
     SevHashTableEntry cmdline;
     SevHashTableEntry initrd;
     SevHashTableEntry kernel;
-    uint8_t padding[];
 } SevHashTable;
 
+/*
+ * Data encrypted by sev_encrypt_flash() must be padded to a multiple of
+ * 16 bytes.
+ */
+typedef struct QEMU_PACKED PaddedSevHashTable {
+    SevHashTable ht;
+    uint8_t padding[ROUND_UP(sizeof(SevHashTable), 16) - sizeof(SevHashTable)];
+} PaddedSevHashTable;
+
+QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0);
+
 static SevGuestState *sev_guest;
 static Error *sev_mig_blocker;
 
@@ -1196,19 +1206,19 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
     uint8_t *data;
     SevHashTableDescriptor *area;
     SevHashTable *ht;
+    PaddedSevHashTable *padded_ht;
     uint8_t cmdline_hash[HASH_SIZE];
     uint8_t initrd_hash[HASH_SIZE];
     uint8_t kernel_hash[HASH_SIZE];
     uint8_t *hashp;
     size_t hash_len = HASH_SIZE;
-    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
 
     if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
         warn_report("SEV: kernel specified but OVMF has no hash table guid");
         return false;
     }
     area = (SevHashTableDescriptor *)data;
-    if (!area->base || area->size < aligned_len) {
+    if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
         warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
                     area->base, area->size);
         return false;
@@ -1253,7 +1263,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
      * Populate the hashes table in the guest's memory at the OVMF-designated
      * area for the SEV hashes table
      */
-    ht = qemu_map_ram_ptr(NULL, area->base);
+    padded_ht = qemu_map_ram_ptr(NULL, area->base);
+    ht = &padded_ht->ht;
 
     ht->guid = sev_hash_table_header_guid;
     ht->len = sizeof(*ht);
@@ -1270,13 +1281,10 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
     ht->kernel.len = sizeof(ht->kernel);
     memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
 
-    /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
-    if (aligned_len != ht->len) {
-        /* zero the excess data so the measurement can be reliably calculated */
-        memset(ht->padding, 0, aligned_len - ht->len);
-    }
+    /* zero the excess data so the measurement can be reliably calculated */
+    memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
 
-    if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) {
+    if (sev_encrypt_flash((uint8_t *)padded_ht, sizeof(*padded_ht), errp) < 0) {
         return false;
     }
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
@ 2021-11-01 14:25   ` Tom Lendacky
  2021-11-01 17:56     ` Dov Murik
  2021-11-03 16:02   ` Daniel P. Berrangé
  1 sibling, 1 reply; 29+ messages in thread
From: Tom Lendacky @ 2021-11-01 14:25 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: Paolo Bonzini, Marcelo Tosatti, Dr. David Alan Gilbert,
	Eduardo Habkost, Philippe Mathieu-Daudé,
	Ashish Kalra, Brijesh Singh, Tobin Feldman-Fitzthum,
	James Bottomley

On 11/1/21 5:21 AM, Dov Murik wrote:
> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> for measured linux boot", 2021-09-30) introduced measured direct boot
> with -kernel, using an OVMF-designated hashes table which QEMU fills.
> 
> However, if OVMF doesn't designate such an area, QEMU would completely
> abort the VM launch.  This breaks launching with -kernel using older
> OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
> 
> Instead, just warn the user that -kernel was supplied by OVMF doesn't
> specify the GUID for the hashes table.  The following warning will be
> displayed during VM launch:
> 
>      qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> Reported-by: Tom Lendacky <thomas.lendacky@amd.com>

Just a few minor comments/questions below, otherwise:

Acked-by: Tom Lendacky <thomas.lendacky@amd.com>

> ---
>   target/i386/sev.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index eede07f11d..682b8ccf6c 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>       int aligned_len;
>   
>       if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
> -        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
> +        warn_report("SEV: kernel specified but OVMF has no hash table guid");

Not sure if warn or info would be better, either way works for me, though, 
since this allows the guest to boot now.

Unrelated to this change, but do we explicitly want to say OVMF? Can't 
another BIOS/UEFI implementation have this support?

and should guid be GUID?

Thanks,
Tom

>           return false;
>       }
>       area = (SevHashTableDescriptor *)data;
> 


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-01 14:25   ` Tom Lendacky
@ 2021-11-01 17:56     ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-01 17:56 UTC (permalink / raw)
  To: Tom Lendacky, qemu-devel
  Cc: Ashish Kalra, Brijesh Singh, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, Dr. David Alan Gilbert, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 01/11/2021 16:25, Tom Lendacky wrote:
> On 11/1/21 5:21 AM, Dov Murik wrote:
>> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
>> for measured linux boot", 2021-09-30) introduced measured direct boot
>> with -kernel, using an OVMF-designated hashes table which QEMU fills.
>>
>> However, if OVMF doesn't designate such an area, QEMU would completely
>> abort the VM launch.  This breaks launching with -kernel using older
>> OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
>>
>> Instead, just warn the user that -kernel was supplied by OVMF doesn't
>> specify the GUID for the hashes table.  The following warning will be
>> displayed during VM launch:
>>
>>      qemu-system-x86_64: warning: SEV: kernel specified but OVMF has
>> no hash table guid
>>
>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
>> Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> Just a few minor comments/questions below, otherwise:
> 
> Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
>> ---
>>   target/i386/sev.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/target/i386/sev.c b/target/i386/sev.c
>> index eede07f11d..682b8ccf6c 100644
>> --- a/target/i386/sev.c
>> +++ b/target/i386/sev.c
>> @@ -1204,7 +1204,7 @@ bool
>> sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>>       int aligned_len;
>>         if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data,
>> NULL)) {
>> -        error_setg(errp, "SEV: kernel specified but OVMF has no hash
>> table guid");
>> +        warn_report("SEV: kernel specified but OVMF has no hash table
>> guid");
> 
> Not sure if warn or info would be better, either way works for me,
> though, since this allows the guest to boot now.

OK.

> 
> Unrelated to this change, but do we explicitly want to say OVMF? Can't
> another BIOS/UEFI implementation have this support?
> 

I don't mind saying "guest firmware" or "VM firmware" or "guest flash"
instead.  Note that the function name has "ovmf" in it...


> and should guid be GUID?

I agree; if we change "OVMF" I'll fix that as well.

-Dov


> 
> Thanks,
> Tom
> 
>>           return false;
>>       }
>>       area = (SevHashTableDescriptor *)data;
>>


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-01 10:21 [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Dov Murik
                   ` (2 preceding siblings ...)
  2021-11-01 10:21 ` [PATCH 3/3] sev/i386: Perform padding calculations at compile-time Dov Murik
@ 2021-11-02 10:52 ` Brijesh Singh
  2021-11-02 13:22   ` Dov Murik
  3 siblings, 1 reply; 29+ messages in thread
From: Brijesh Singh @ 2021-11-02 10:52 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: brijesh.singh, Paolo Bonzini, Marcelo Tosatti,
	Dr. David Alan Gilbert, Eduardo Habkost,
	Philippe Mathieu-Daudé,
	Ashish Kalra, Tom Lendacky, Tobin Feldman-Fitzthum,
	James Bottomley

Hi Dov,

Overall the patch looks good, only question I have is that now we are
enforce qemu to hash the kernel, initrd and cmdline unconditionally for
any of the SEV guest launches. This requires anyone wanting to
calculating the expected measurement need to account for it. Should we
make the hash page build optional ?

I am thinking this more for the SEV-SNP guest. As you may be aware that
with SEV-SNP the attestation is performed by the guest, and its possible
for the launch flow to pass 512-bits of host_data that gets included in
the report. If a user wants to do the hash'e checks for the SNP then
they can pass a hash of kernel, initrd and cmdline through a
launch_finish.ID_BLOCK.host_data and does not require a special hash
page. This it will simplify the expected hash calculation. Adding a
special page requires a validation of that page. All the prevalidated
page need to be excluded by guest BIOS page validation flow to avoid the
double validation. The hash page is populated only when we pass -kernel
and it will be tricky to communicate this information to the guest BIOS
so that it can skip the validation.

Thoughts ?

thanks

On 11/1/21 5:21 AM, Dov Murik wrote:
> Tom Lendacky and Brijesh Singh reported two issues with launching SEV
> guests with the -kernel QEMU option when an old [1] or wrongly configured [2]
> OVMF images are used.
>
> The fixes in patches 1 and 2 allow such guests to boot by skipping the
> kernel/initrd/cmdline hashes addition to the initial guest memory (and
> warning the user).
>
> Patch 3 is a refactoring of parts of the same function
> sev_add_kernel_loader_hashes() to calculate all padding sizes at
> compile-time.  This patch is not required to fix the issues above, but
> is suggested as an improvement (no functional change intended).
>
> Note that launch measurement security is not harmed by these fixes: a
> Guest Owner that wants to use measured Linux boot with -kernel, must use
> (and measure) an OVMF image that designates a proper hashes table area,
> and that verifies those hashes when loading the binaries from QEMU via
> fw_cfg.
>
> The old OVMFs which don't publish the hashes table GUID or don't reserve
> a valid area for it in MEMFD cannot support these hashes verification in
> any case (for measured boot with -kernel).
>
>
> [1] https://lore.kernel.org/qemu-devel/3b9d10d9-5d9c-da52-f18c-cd93c1931706@amd.com/
> [2] https://lore.kernel.org/qemu-devel/001dd81a-282d-c307-a657-e228480d4af3@amd.com/
>
> Dov Murik (3):
>   sev/i386: Allow launching with -kernel if no OVMF hashes table found
>   sev/i386: Warn if using -kernel with invalid OVMF hashes table area
>   sev/i386: Perform padding calculations at compile-time
>
>  target/i386/sev.c | 34 +++++++++++++++++++++++-----------
>  1 file changed, 23 insertions(+), 11 deletions(-)
>
>
> base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 3/3] sev/i386: Perform padding calculations at compile-time
  2021-11-01 10:21 ` [PATCH 3/3] sev/i386: Perform padding calculations at compile-time Dov Murik
@ 2021-11-02 11:36   ` Dr. David Alan Gilbert
  2021-11-02 11:50     ` Dov Murik
  2021-11-03 14:49   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 29+ messages in thread
From: Dr. David Alan Gilbert @ 2021-11-02 11:36 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Dov Murik (dovmurik@linux.ibm.com) wrote:
> In sev_add_kernel_loader_hashes, the sizes of structs are known at
> compile-time, so calculate needed padding at compile-time.
> 
> No functional change intended.
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>



Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

> ---
>  target/i386/sev.c | 28 ++++++++++++++++++----------
>  1 file changed, 18 insertions(+), 10 deletions(-)
> 
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index a20ddb545e..c09de9c6f0 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -109,9 +109,19 @@ typedef struct QEMU_PACKED SevHashTable {
>      SevHashTableEntry cmdline;
>      SevHashTableEntry initrd;
>      SevHashTableEntry kernel;
> -    uint8_t padding[];
>  } SevHashTable;
>  
> +/*
> + * Data encrypted by sev_encrypt_flash() must be padded to a multiple of
> + * 16 bytes.
> + */
> +typedef struct QEMU_PACKED PaddedSevHashTable {
> +    SevHashTable ht;
> +    uint8_t padding[ROUND_UP(sizeof(SevHashTable), 16) - sizeof(SevHashTable)];
> +} PaddedSevHashTable;
> +
> +QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0);
> +
>  static SevGuestState *sev_guest;
>  static Error *sev_mig_blocker;
>  
> @@ -1196,19 +1206,19 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      uint8_t *data;
>      SevHashTableDescriptor *area;
>      SevHashTable *ht;
> +    PaddedSevHashTable *padded_ht;
>      uint8_t cmdline_hash[HASH_SIZE];
>      uint8_t initrd_hash[HASH_SIZE];
>      uint8_t kernel_hash[HASH_SIZE];
>      uint8_t *hashp;
>      size_t hash_len = HASH_SIZE;
> -    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
>  
>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
>          return false;
>      }
>      area = (SevHashTableDescriptor *)data;
> -    if (!area->base || area->size < aligned_len) {
> +    if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
>          warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
>                      area->base, area->size);
>          return false;
> @@ -1253,7 +1263,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>       * Populate the hashes table in the guest's memory at the OVMF-designated
>       * area for the SEV hashes table
>       */
> -    ht = qemu_map_ram_ptr(NULL, area->base);
> +    padded_ht = qemu_map_ram_ptr(NULL, area->base);
> +    ht = &padded_ht->ht;
>  
>      ht->guid = sev_hash_table_header_guid;
>      ht->len = sizeof(*ht);
> @@ -1270,13 +1281,10 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      ht->kernel.len = sizeof(ht->kernel);
>      memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
>  
> -    /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
> -    if (aligned_len != ht->len) {
> -        /* zero the excess data so the measurement can be reliably calculated */
> -        memset(ht->padding, 0, aligned_len - ht->len);
> -    }
> +    /* zero the excess data so the measurement can be reliably calculated */
> +    memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
>  
> -    if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) {
> +    if (sev_encrypt_flash((uint8_t *)padded_ht, sizeof(*padded_ht), errp) < 0) {
>          return false;
>      }
>  
> -- 
> 2.25.1
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 3/3] sev/i386: Perform padding calculations at compile-time
  2021-11-02 11:36   ` Dr. David Alan Gilbert
@ 2021-11-02 11:50     ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-02 11:50 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 02/11/2021 13:36, Dr. David Alan Gilbert wrote:
> * Dov Murik (dovmurik@linux.ibm.com) wrote:
>> In sev_add_kernel_loader_hashes, the sizes of structs are known at
>> compile-time, so calculate needed padding at compile-time.
>>
>> No functional change intended.
>>
>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> 
> 
> 
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> 

Thanks Dave.

-Dov



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-01 10:21 ` [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area Dov Murik
@ 2021-11-02 12:36   ` Dr. David Alan Gilbert
  2021-11-02 12:56     ` Dov Murik
  2021-11-03 16:07   ` Daniel P. Berrangé
  1 sibling, 1 reply; 29+ messages in thread
From: Dr. David Alan Gilbert @ 2021-11-02 12:36 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Dov Murik (dovmurik@linux.ibm.com) wrote:
> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> for measured linux boot", 2021-09-30) introduced measured direct boot
> with -kernel, using an OVMF-designated hashes table which QEMU fills.
> 
> However, no checks are performed on the validity of the hashes area
> designated by OVMF.  Specifically, if OVMF publishes the
> SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
> cause QEMU to write the hashes entries over the first page of the
> guest's memory (GPA 0).
> 
> Add validity checks to the published area.  If the hashes table area's
> base address is zero, or its size is too small to fit the aligned hashes
> table, warn and skip the hashes entries addition.  In such case, the
> following warning will be displayed:
> 
>     qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> Reported-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  target/i386/sev.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index 682b8ccf6c..a20ddb545e 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      uint8_t kernel_hash[HASH_SIZE];
>      uint8_t *hashp;
>      size_t hash_len = HASH_SIZE;
> -    int aligned_len;
> +    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
>  
>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
>          return false;
>      }
>      area = (SevHashTableDescriptor *)data;
> +    if (!area->base || area->size < aligned_len) {
> +        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
> +                    area->base, area->size);
> +        return false;
> +    }

That's probably a useful check, so


Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

however, maybe it needs to be more thorough before using area->base to
qemu_map_ram_ptr? - I think it'll get unhappy if it's a bad address not
in a ram block. (Or check you're running over the end of a ramblock)

Dave

>  
>      /*
>       * Calculate hash of kernel command-line with the terminating null byte. If
> @@ -1266,7 +1271,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
>  
>      /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
> -    aligned_len = ROUND_UP(ht->len, 16);
>      if (aligned_len != ht->len) {
>          /* zero the excess data so the measurement can be reliably calculated */
>          memset(ht->padding, 0, aligned_len - ht->len);
> -- 
> 2.25.1
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-02 12:36   ` Dr. David Alan Gilbert
@ 2021-11-02 12:56     ` Dov Murik
  2021-11-02 18:38       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 29+ messages in thread
From: Dov Murik @ 2021-11-02 12:56 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 02/11/2021 14:36, Dr. David Alan Gilbert wrote:
> * Dov Murik (dovmurik@linux.ibm.com) wrote:
>> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
>> for measured linux boot", 2021-09-30) introduced measured direct boot
>> with -kernel, using an OVMF-designated hashes table which QEMU fills.
>>
>> However, no checks are performed on the validity of the hashes area
>> designated by OVMF.  Specifically, if OVMF publishes the
>> SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
>> cause QEMU to write the hashes entries over the first page of the
>> guest's memory (GPA 0).
>>
>> Add validity checks to the published area.  If the hashes table area's
>> base address is zero, or its size is too small to fit the aligned hashes
>> table, warn and skip the hashes entries addition.  In such case, the
>> following warning will be displayed:
>>
>>     qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)
>>
>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
>> Reported-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  target/i386/sev.c | 8 ++++++--
>>  1 file changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/target/i386/sev.c b/target/i386/sev.c
>> index 682b8ccf6c..a20ddb545e 100644
>> --- a/target/i386/sev.c
>> +++ b/target/i386/sev.c
>> @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>>      uint8_t kernel_hash[HASH_SIZE];
>>      uint8_t *hashp;
>>      size_t hash_len = HASH_SIZE;
>> -    int aligned_len;
>> +    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
>>  
>>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
>>          return false;
>>      }
>>      area = (SevHashTableDescriptor *)data;
>> +    if (!area->base || area->size < aligned_len) {
>> +        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
>> +                    area->base, area->size);
>> +        return false;
>> +    }
> 
> That's probably a useful check, so
> 
> 
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> 

Thanks.


> however, maybe it needs to be more thorough before using area->base to
> qemu_map_ram_ptr? - I think it'll get unhappy if it's a bad address not
> in a ram block. (Or check you're running over the end of a ramblock)
>

Does address_space_write perform these checks? Or maybe another API for
accessing the guest's RAM?

-Dov

> Dave
> 
>>  
>>      /*
>>       * Calculate hash of kernel command-line with the terminating null byte. If
>> @@ -1266,7 +1271,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>>      memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
>>  
>>      /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
>> -    aligned_len = ROUND_UP(ht->len, 16);
>>      if (aligned_len != ht->len) {
>>          /* zero the excess data so the measurement can be reliably calculated */
>>          memset(ht->padding, 0, aligned_len - ht->len);
>> -- 
>> 2.25.1
>>


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-02 10:52 ` [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Brijesh Singh
@ 2021-11-02 13:22   ` Dov Murik
  2021-11-02 14:48     ` Brijesh Singh
  2021-11-03 16:10     ` Daniel P. Berrangé
  0 siblings, 2 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-02 13:22 UTC (permalink / raw)
  To: Brijesh Singh, qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, Dr. David Alan Gilbert, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 02/11/2021 12:52, Brijesh Singh wrote:
> Hi Dov,
> 
> Overall the patch looks good, only question I have is that now we are
> enforce qemu to hash the kernel, initrd and cmdline unconditionally for
> any of the SEV guest launches. This requires anyone wanting to
> calculating the expected measurement need to account for it. Should we
> make the hash page build optional ?
> 

The problem with adding a -enable-add-kernel-hashes QEMU option (or
suboption) is yet another complexity for the user.  I'd also argue that
adding these hashes can lead to a more secure VM boot process, so it
makes sense for it to be the default (and maybe introduce a
-allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
measurement from changing due to addition of hashes?).

Maybe, on the other hand, OVMF should "report" whether it supports
hashes verification. If it does, it should have the GUID in the table
(near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
it doesn't support that, then the entry should not appear at all, and
then QEMU won't add the hashes (with patch 1 from this series).  This
means that in edk2 we need to remove the SEV Hash Table block from the
ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.

But the problem with this approach is that it prevents the future
unification of AmdSev and OvmfPkg, which is a possibility we discussed
(at least with Dave Gilbert), though not sure it's a good/feasible goal.



> I am thinking this more for the SEV-SNP guest. As you may be aware that
> with SEV-SNP the attestation is performed by the guest, and its possible
> for the launch flow to pass 512-bits of host_data that gets included in
> the report. If a user wants to do the hash'e checks for the SNP then
> they can pass a hash of kernel, initrd and cmdline through a
> launch_finish.ID_BLOCK.host_data and does not require a special hash
> page. This it will simplify the expected hash calculation.

That is a new measured boot "protocol" that we can discuss, and see
whether it's better/easier than the existing one at hand that works on
SEV and SEV-ES.

What I don't understand in your suggestion is who performs a SHA256 of
the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
(though ideally earlier is better).  Can you describe the details
(step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
the measurement/attestation is performed?



> Adding a
> special page requires a validation of that page. All the prevalidated
> page need to be excluded by guest BIOS page validation flow to avoid the
> double validation. The hash page is populated only when we pass -kernel
> and it will be tricky to communicate this information to the guest BIOS
> so that it can skip the validation.

So that again comes back to the earlier question of whether we should
always fill the hashes page or only sometimes, and how can OVMF tell.

How about: QEMU always prevalidates this page (either fills it with
zeros or with the hashes table), and the BIOS always excludes it?

-Dov


> 
> Thoughts ?
> 
> thanks
> 
> On 11/1/21 5:21 AM, Dov Murik wrote:
>> Tom Lendacky and Brijesh Singh reported two issues with launching SEV
>> guests with the -kernel QEMU option when an old [1] or wrongly configured [2]
>> OVMF images are used.
>>
>> The fixes in patches 1 and 2 allow such guests to boot by skipping the
>> kernel/initrd/cmdline hashes addition to the initial guest memory (and
>> warning the user).
>>
>> Patch 3 is a refactoring of parts of the same function
>> sev_add_kernel_loader_hashes() to calculate all padding sizes at
>> compile-time.  This patch is not required to fix the issues above, but
>> is suggested as an improvement (no functional change intended).
>>
>> Note that launch measurement security is not harmed by these fixes: a
>> Guest Owner that wants to use measured Linux boot with -kernel, must use
>> (and measure) an OVMF image that designates a proper hashes table area,
>> and that verifies those hashes when loading the binaries from QEMU via
>> fw_cfg.
>>
>> The old OVMFs which don't publish the hashes table GUID or don't reserve
>> a valid area for it in MEMFD cannot support these hashes verification in
>> any case (for measured boot with -kernel).
>>
>>
>> [1] https://lore.kernel.org/qemu-devel/3b9d10d9-5d9c-da52-f18c-cd93c1931706@amd.com/
>> [2] https://lore.kernel.org/qemu-devel/001dd81a-282d-c307-a657-e228480d4af3@amd.com/
>>
>> Dov Murik (3):
>>   sev/i386: Allow launching with -kernel if no OVMF hashes table found
>>   sev/i386: Warn if using -kernel with invalid OVMF hashes table area
>>   sev/i386: Perform padding calculations at compile-time
>>
>>  target/i386/sev.c | 34 +++++++++++++++++++++++-----------
>>  1 file changed, 23 insertions(+), 11 deletions(-)
>>
>>
>> base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-02 13:22   ` Dov Murik
@ 2021-11-02 14:48     ` Brijesh Singh
  2021-11-03 14:08       ` Dr. David Alan Gilbert
  2021-11-05 18:32       ` Dov Murik
  2021-11-03 16:10     ` Daniel P. Berrangé
  1 sibling, 2 replies; 29+ messages in thread
From: Brijesh Singh @ 2021-11-02 14:48 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: brijesh.singh, Paolo Bonzini, Marcelo Tosatti,
	Dr. David Alan Gilbert, Eduardo Habkost,
	Philippe Mathieu-Daudé,
	Ashish Kalra, Tom Lendacky, Tobin Feldman-Fitzthum,
	James Bottomley



On 11/2/21 8:22 AM, Dov Murik wrote:
> 
> 
> On 02/11/2021 12:52, Brijesh Singh wrote:
>> Hi Dov,
>>
>> Overall the patch looks good, only question I have is that now we are
>> enforce qemu to hash the kernel, initrd and cmdline unconditionally for
>> any of the SEV guest launches. This requires anyone wanting to
>> calculating the expected measurement need to account for it. Should we
>> make the hash page build optional ?
>>
> 
> The problem with adding a -enable-add-kernel-hashes QEMU option (or
> suboption) is yet another complexity for the user.  I'd also argue that
> adding these hashes can lead to a more secure VM boot process, so it
> makes sense for it to be the default (and maybe introduce a
> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
> measurement from changing due to addition of hashes?).
> 
> Maybe, on the other hand, OVMF should "report" whether it supports
> hashes verification. If it does, it should have the GUID in the table
> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
> it doesn't support that, then the entry should not appear at all, and
> then QEMU won't add the hashes (with patch 1 from this series).  This
> means that in edk2 we need to remove the SEV Hash Table block from the
> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
> 

By leaving it ON is conveying a wrong message to the user. The library 
used for verifying the hash is a NULL library for all the builds of Ovmf 
except the AmdSev package. In the NULL library case, OVMF does not 
perform any checks and hash table is useless. I will raise this on 
concern on your Ovmf patch series.

IMHO, if you want to turn it ON by default then make sure all the OVMF 
package builds supports validating the hash.


> But the problem with this approach is that it prevents the future
> unification of AmdSev and OvmfPkg, which is a possibility we discussed
> (at least with Dave Gilbert), though not sure it's a good/feasible goal.
> 
> 

This is my exact concern, we are auto enabling the features in Qemu that 
is supported by AmdSev package only.


> 
>> I am thinking this more for the SEV-SNP guest. As you may be aware that
>> with SEV-SNP the attestation is performed by the guest, and its possible
>> for the launch flow to pass 512-bits of host_data that gets included in
>> the report. If a user wants to do the hash'e checks for the SNP then
>> they can pass a hash of kernel, initrd and cmdline through a
>> launch_finish.ID_BLOCK.host_data and does not require a special hash
>> page. This it will simplify the expected hash calculation.
> 
> That is a new measured boot "protocol" that we can discuss, and see
> whether it's better/easier than the existing one at hand that works on
> SEV and SEV-ES.
> 
> What I don't understand in your suggestion is who performs a SHA256 of
> the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
> (though ideally earlier is better).  Can you describe the details
> (step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
> the measurement/attestation is performed?
> 
> 

There are a multiple ways on how you can do a measured boot with the SNP.

1) VMPL0 (SVSM) can provide a complete vTPM (see the MSFT proposal on 
SNP mailing list).

2) Use your existing hashing approach with some changes to provide a bit 
more flexibility.

3) Use your existing hashing approach but zero out the hash page when 
-kernel is not used.

Let me expand #2.

While launching the SNP guest, a guest owner can provide a ID block that 
KVM will pass to the PSP during the guest launch flow. In the ID block 
there is a field called "host_data". A guest owner can do a hash of 
kernel/initrd/cmdline and include it in the "host_data" field. During 
the hash verification, the OVMF can call the SNP_GET_REPORT. The PSP 
will includes the "host_data" passed in the launch process in the report 
and OVMF can use it for the verification. Unlike the current 
implementation, this enables a guest owner to provides the hash without 
requiring any changes in the Qemu and thus affecting the measurement.

One thing to note that both #2 and #3 requires ovmf to connect to guest 
owner to validate the report before using the "host_data" or "hash page".


thanks

> 
>> Adding a
>> special page requires a validation of that page. All the prevalidated
>> page need to be excluded by guest BIOS page validation flow to avoid the
>> double validation. The hash page is populated only when we pass -kernel
>> and it will be tricky to communicate this information to the guest BIOS
>> so that it can skip the validation.
> 
> So that again comes back to the earlier question of whether we should
> always fill the hashes page or only sometimes, and how can OVMF tell.
> 
> How about: QEMU always prevalidates this page (either fills it with
> zeros or with the hashes table), and the BIOS always excludes it?
> 
> -Dov
> 
> 
>>
>> Thoughts ?
>>
>> thanks
>>
>> On 11/1/21 5:21 AM, Dov Murik wrote:
>>> Tom Lendacky and Brijesh Singh reported two issues with launching SEV
>>> guests with the -kernel QEMU option when an old [1] or wrongly configured [2]
>>> OVMF images are used.
>>>
>>> The fixes in patches 1 and 2 allow such guests to boot by skipping the
>>> kernel/initrd/cmdline hashes addition to the initial guest memory (and
>>> warning the user).
>>>
>>> Patch 3 is a refactoring of parts of the same function
>>> sev_add_kernel_loader_hashes() to calculate all padding sizes at
>>> compile-time.  This patch is not required to fix the issues above, but
>>> is suggested as an improvement (no functional change intended).
>>>
>>> Note that launch measurement security is not harmed by these fixes: a
>>> Guest Owner that wants to use measured Linux boot with -kernel, must use
>>> (and measure) an OVMF image that designates a proper hashes table area,
>>> and that verifies those hashes when loading the binaries from QEMU via
>>> fw_cfg.
>>>
>>> The old OVMFs which don't publish the hashes table GUID or don't reserve
>>> a valid area for it in MEMFD cannot support these hashes verification in
>>> any case (for measured boot with -kernel).
>>>
>>>
>>> [1] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fqemu-devel%2F3b9d10d9-5d9c-da52-f18c-cd93c1931706%40amd.com%2F&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cffa0a5981860476c3bcc08d99e03d3d7%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637714561554218974%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=591wZvEzQQQ6JBjLDhGnvEM8fxX6iky9yxlWn2pifjI%3D&amp;reserved=0
>>> [2] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fqemu-devel%2F001dd81a-282d-c307-a657-e228480d4af3%40amd.com%2F&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cffa0a5981860476c3bcc08d99e03d3d7%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637714561554218974%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=ihwNJjetXq5I0WaLjEFzhtrKMbj%2FaFmOmn1xYlLowjg%3D&amp;reserved=0
>>>
>>> Dov Murik (3):
>>>    sev/i386: Allow launching with -kernel if no OVMF hashes table found
>>>    sev/i386: Warn if using -kernel with invalid OVMF hashes table area
>>>    sev/i386: Perform padding calculations at compile-time
>>>
>>>   target/i386/sev.c | 34 +++++++++++++++++++++++-----------
>>>   1 file changed, 23 insertions(+), 11 deletions(-)
>>>
>>>
>>> base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-02 12:56     ` Dov Murik
@ 2021-11-02 18:38       ` Dr. David Alan Gilbert
  2021-11-02 19:00         ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 29+ messages in thread
From: Dr. David Alan Gilbert @ 2021-11-02 18:38 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Dov Murik (dovmurik@linux.ibm.com) wrote:
> 
> 
> On 02/11/2021 14:36, Dr. David Alan Gilbert wrote:
> > * Dov Murik (dovmurik@linux.ibm.com) wrote:
> >> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> >> for measured linux boot", 2021-09-30) introduced measured direct boot
> >> with -kernel, using an OVMF-designated hashes table which QEMU fills.
> >>
> >> However, no checks are performed on the validity of the hashes area
> >> designated by OVMF.  Specifically, if OVMF publishes the
> >> SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
> >> cause QEMU to write the hashes entries over the first page of the
> >> guest's memory (GPA 0).
> >>
> >> Add validity checks to the published area.  If the hashes table area's
> >> base address is zero, or its size is too small to fit the aligned hashes
> >> table, warn and skip the hashes entries addition.  In such case, the
> >> following warning will be displayed:
> >>
> >>     qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)
> >>
> >> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> >> Reported-by: Brijesh Singh <brijesh.singh@amd.com>
> >> ---
> >>  target/i386/sev.c | 8 ++++++--
> >>  1 file changed, 6 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/target/i386/sev.c b/target/i386/sev.c
> >> index 682b8ccf6c..a20ddb545e 100644
> >> --- a/target/i386/sev.c
> >> +++ b/target/i386/sev.c
> >> @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
> >>      uint8_t kernel_hash[HASH_SIZE];
> >>      uint8_t *hashp;
> >>      size_t hash_len = HASH_SIZE;
> >> -    int aligned_len;
> >> +    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
> >>  
> >>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
> >>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
> >>          return false;
> >>      }
> >>      area = (SevHashTableDescriptor *)data;
> >> +    if (!area->base || area->size < aligned_len) {
> >> +        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
> >> +                    area->base, area->size);
> >> +        return false;
> >> +    }
> > 
> > That's probably a useful check, so
> > 
> > 
> > Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> > 
> 
> Thanks.
> 
> 
> > however, maybe it needs to be more thorough before using area->base to
> > qemu_map_ram_ptr? - I think it'll get unhappy if it's a bad address not
> > in a ram block. (Or check you're running over the end of a ramblock)
> >
> 
> Does address_space_write perform these checks? Or maybe another API for
> accessing the guest's RAM?

I'm not sure; for example in address_space_map I don't see an check that
flatview_translate gives a valid mr.

Dave

> -Dov
> 
> > Dave
> > 
> >>  
> >>      /*
> >>       * Calculate hash of kernel command-line with the terminating null byte. If
> >> @@ -1266,7 +1271,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
> >>      memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
> >>  
> >>      /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
> >> -    aligned_len = ROUND_UP(ht->len, 16);
> >>      if (aligned_len != ht->len) {
> >>          /* zero the excess data so the measurement can be reliably calculated */
> >>          memset(ht->padding, 0, aligned_len - ht->len);
> >> -- 
> >> 2.25.1
> >>
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-02 18:38       ` Dr. David Alan Gilbert
@ 2021-11-02 19:00         ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 29+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-11-02 19:00 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Dov Murik, Peter Xu, David Hildenbrand
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Tobin Feldman-Fitzthum, Paolo Bonzini

On 11/2/21 19:38, Dr. David Alan Gilbert wrote:
> * Dov Murik (dovmurik@linux.ibm.com) wrote:

>>> however, maybe it needs to be more thorough before using area->base to
>>> qemu_map_ram_ptr? - I think it'll get unhappy if it's a bad address not
>>> in a ram block. (Or check you're running over the end of a ramblock)
>>>
>>
>> Does address_space_write perform these checks? Or maybe another API for
>> accessing the guest's RAM?
> 
> I'm not sure; for example in address_space_map I don't see an check that
> flatview_translate gives a valid mr.

IIUC the API the MemTxAttrs argument could help you, but I don't think
properly enforced (yet?...).



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-02 14:48     ` Brijesh Singh
@ 2021-11-03 14:08       ` Dr. David Alan Gilbert
  2021-11-03 15:44         ` Brijesh Singh
  2021-11-05 18:32       ` Dov Murik
  1 sibling, 1 reply; 29+ messages in thread
From: Dr. David Alan Gilbert @ 2021-11-03 14:08 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Tom Lendacky, Ashish Kalra, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, qemu-devel, Dov Murik, Tobin Feldman-Fitzthum,
	Paolo Bonzini, Philippe Mathieu-Daudé

* Brijesh Singh (brijesh.singh@amd.com) wrote:
> 
> 
> On 11/2/21 8:22 AM, Dov Murik wrote:
> > 
> > 
> > On 02/11/2021 12:52, Brijesh Singh wrote:
> > > Hi Dov,
> > > 
> > > Overall the patch looks good, only question I have is that now we are
> > > enforce qemu to hash the kernel, initrd and cmdline unconditionally for
> > > any of the SEV guest launches. This requires anyone wanting to
> > > calculating the expected measurement need to account for it. Should we
> > > make the hash page build optional ?
> > > 
> > 
> > The problem with adding a -enable-add-kernel-hashes QEMU option (or
> > suboption) is yet another complexity for the user.  I'd also argue that
> > adding these hashes can lead to a more secure VM boot process, so it
> > makes sense for it to be the default (and maybe introduce a
> > -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
> > measurement from changing due to addition of hashes?).
> > 
> > Maybe, on the other hand, OVMF should "report" whether it supports
> > hashes verification. If it does, it should have the GUID in the table
> > (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
> > it doesn't support that, then the entry should not appear at all, and
> > then QEMU won't add the hashes (with patch 1 from this series).  This
> > means that in edk2 we need to remove the SEV Hash Table block from the
> > ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
> > 
> 
> By leaving it ON is conveying a wrong message to the user. The library used
> for verifying the hash is a NULL library for all the builds of Ovmf except
> the AmdSev package. In the NULL library case, OVMF does not perform any
> checks and hash table is useless. I will raise this on concern on your Ovmf
> patch series.
> 
> IMHO, if you want to turn it ON by default then make sure all the OVMF
> package builds supports validating the hash.
> 
> 
> > But the problem with this approach is that it prevents the future
> > unification of AmdSev and OvmfPkg, which is a possibility we discussed
> > (at least with Dave Gilbert), though not sure it's a good/feasible goal.
> > 
> > 
> 
> This is my exact concern, we are auto enabling the features in Qemu that is
> supported by AmdSev package only.

I'm confused; wouldn't the trick be to only define the GUIDs for the
builds that support the validation?

Dave

> 
> > 
> > > I am thinking this more for the SEV-SNP guest. As you may be aware that
> > > with SEV-SNP the attestation is performed by the guest, and its possible
> > > for the launch flow to pass 512-bits of host_data that gets included in
> > > the report. If a user wants to do the hash'e checks for the SNP then
> > > they can pass a hash of kernel, initrd and cmdline through a
> > > launch_finish.ID_BLOCK.host_data and does not require a special hash
> > > page. This it will simplify the expected hash calculation.
> > 
> > That is a new measured boot "protocol" that we can discuss, and see
> > whether it's better/easier than the existing one at hand that works on
> > SEV and SEV-ES.
> > 
> > What I don't understand in your suggestion is who performs a SHA256 of
> > the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
> > (though ideally earlier is better).  Can you describe the details
> > (step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
> > the measurement/attestation is performed?
> > 
> > 
> 
> There are a multiple ways on how you can do a measured boot with the SNP.
> 
> 1) VMPL0 (SVSM) can provide a complete vTPM (see the MSFT proposal on SNP
> mailing list).
> 
> 2) Use your existing hashing approach with some changes to provide a bit
> more flexibility.
> 
> 3) Use your existing hashing approach but zero out the hash page when
> -kernel is not used.
> 
> Let me expand #2.
> 
> While launching the SNP guest, a guest owner can provide a ID block that KVM
> will pass to the PSP during the guest launch flow. In the ID block there is
> a field called "host_data". A guest owner can do a hash of
> kernel/initrd/cmdline and include it in the "host_data" field. During the
> hash verification, the OVMF can call the SNP_GET_REPORT. The PSP will
> includes the "host_data" passed in the launch process in the report and OVMF
> can use it for the verification. Unlike the current implementation, this
> enables a guest owner to provides the hash without requiring any changes in
> the Qemu and thus affecting the measurement.
> 
> One thing to note that both #2 and #3 requires ovmf to connect to guest
> owner to validate the report before using the "host_data" or "hash page".
> 
> 
> thanks
> 
> > 
> > > Adding a
> > > special page requires a validation of that page. All the prevalidated
> > > page need to be excluded by guest BIOS page validation flow to avoid the
> > > double validation. The hash page is populated only when we pass -kernel
> > > and it will be tricky to communicate this information to the guest BIOS
> > > so that it can skip the validation.
> > 
> > So that again comes back to the earlier question of whether we should
> > always fill the hashes page or only sometimes, and how can OVMF tell.
> > 
> > How about: QEMU always prevalidates this page (either fills it with
> > zeros or with the hashes table), and the BIOS always excludes it?
> > 
> > -Dov
> > 
> > 
> > > 
> > > Thoughts ?
> > > 
> > > thanks
> > > 
> > > On 11/1/21 5:21 AM, Dov Murik wrote:
> > > > Tom Lendacky and Brijesh Singh reported two issues with launching SEV
> > > > guests with the -kernel QEMU option when an old [1] or wrongly configured [2]
> > > > OVMF images are used.
> > > > 
> > > > The fixes in patches 1 and 2 allow such guests to boot by skipping the
> > > > kernel/initrd/cmdline hashes addition to the initial guest memory (and
> > > > warning the user).
> > > > 
> > > > Patch 3 is a refactoring of parts of the same function
> > > > sev_add_kernel_loader_hashes() to calculate all padding sizes at
> > > > compile-time.  This patch is not required to fix the issues above, but
> > > > is suggested as an improvement (no functional change intended).
> > > > 
> > > > Note that launch measurement security is not harmed by these fixes: a
> > > > Guest Owner that wants to use measured Linux boot with -kernel, must use
> > > > (and measure) an OVMF image that designates a proper hashes table area,
> > > > and that verifies those hashes when loading the binaries from QEMU via
> > > > fw_cfg.
> > > > 
> > > > The old OVMFs which don't publish the hashes table GUID or don't reserve
> > > > a valid area for it in MEMFD cannot support these hashes verification in
> > > > any case (for measured boot with -kernel).
> > > > 
> > > > 
> > > > [1] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fqemu-devel%2F3b9d10d9-5d9c-da52-f18c-cd93c1931706%40amd.com%2F&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cffa0a5981860476c3bcc08d99e03d3d7%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637714561554218974%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=591wZvEzQQQ6JBjLDhGnvEM8fxX6iky9yxlWn2pifjI%3D&amp;reserved=0
> > > > [2] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fqemu-devel%2F001dd81a-282d-c307-a657-e228480d4af3%40amd.com%2F&amp;data=04%7C01%7Cbrijesh.singh%40amd.com%7Cffa0a5981860476c3bcc08d99e03d3d7%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637714561554218974%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=ihwNJjetXq5I0WaLjEFzhtrKMbj%2FaFmOmn1xYlLowjg%3D&amp;reserved=0
> > > > 
> > > > Dov Murik (3):
> > > >    sev/i386: Allow launching with -kernel if no OVMF hashes table found
> > > >    sev/i386: Warn if using -kernel with invalid OVMF hashes table area
> > > >    sev/i386: Perform padding calculations at compile-time
> > > > 
> > > >   target/i386/sev.c | 34 +++++++++++++++++++++++-----------
> > > >   1 file changed, 23 insertions(+), 11 deletions(-)
> > > > 
> > > > 
> > > > base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 3/3] sev/i386: Perform padding calculations at compile-time
  2021-11-01 10:21 ` [PATCH 3/3] sev/i386: Perform padding calculations at compile-time Dov Murik
  2021-11-02 11:36   ` Dr. David Alan Gilbert
@ 2021-11-03 14:49   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 29+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-11-03 14:49 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, Dr. David Alan Gilbert,
	Tobin Feldman-Fitzthum, Paolo Bonzini

On 11/1/21 11:21, Dov Murik wrote:
> In sev_add_kernel_loader_hashes, the sizes of structs are known at
> compile-time, so calculate needed padding at compile-time.
> 
> No functional change intended.
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> ---
>  target/i386/sev.c | 28 ++++++++++++++++++----------
>  1 file changed, 18 insertions(+), 10 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-03 14:08       ` Dr. David Alan Gilbert
@ 2021-11-03 15:44         ` Brijesh Singh
  2021-11-05  7:38           ` Dov Murik
  0 siblings, 1 reply; 29+ messages in thread
From: Brijesh Singh @ 2021-11-03 15:44 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: brijesh.singh, Dov Murik, qemu-devel, Paolo Bonzini,
	Marcelo Tosatti, Eduardo Habkost, Philippe Mathieu-Daudé,
	Ashish Kalra, Tom Lendacky, Tobin Feldman-Fitzthum,
	James Bottomley



On 11/3/21 9:08 AM, Dr. David Alan Gilbert wrote:
> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>>
>>
>> On 11/2/21 8:22 AM, Dov Murik wrote:
>>>
>>>
>>> On 02/11/2021 12:52, Brijesh Singh wrote:
>>>> Hi Dov,
>>>>
>>>> Overall the patch looks good, only question I have is that now we are
>>>> enforce qemu to hash the kernel, initrd and cmdline unconditionally for
>>>> any of the SEV guest launches. This requires anyone wanting to
>>>> calculating the expected measurement need to account for it. Should we
>>>> make the hash page build optional ?
>>>>
>>>
>>> The problem with adding a -enable-add-kernel-hashes QEMU option (or
>>> suboption) is yet another complexity for the user.  I'd also argue that
>>> adding these hashes can lead to a more secure VM boot process, so it
>>> makes sense for it to be the default (and maybe introduce a
>>> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
>>> measurement from changing due to addition of hashes?).
>>>
>>> Maybe, on the other hand, OVMF should "report" whether it supports
>>> hashes verification. If it does, it should have the GUID in the table
>>> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
>>> it doesn't support that, then the entry should not appear at all, and
>>> then QEMU won't add the hashes (with patch 1 from this series).  This
>>> means that in edk2 we need to remove the SEV Hash Table block from the
>>> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
>>>
>>
>> By leaving it ON is conveying a wrong message to the user. The library used
>> for verifying the hash is a NULL library for all the builds of Ovmf except
>> the AmdSev package. In the NULL library case, OVMF does not perform any
>> checks and hash table is useless. I will raise this on concern on your Ovmf
>> patch series.
>>
>> IMHO, if you want to turn it ON by default then make sure all the OVMF
>> package builds supports validating the hash.
>>
>>
>>> But the problem with this approach is that it prevents the future
>>> unification of AmdSev and OvmfPkg, which is a possibility we discussed
>>> (at least with Dave Gilbert), though not sure it's a good/feasible goal.
>>>
>>>
>>
>> This is my exact concern, we are auto enabling the features in Qemu that is
>> supported by AmdSev package only.
> 
> I'm confused; wouldn't the trick be to only define the GUIDs for the
> builds that support the validation?
> 

The GUID is hardcoded in the OVMF reset vector asm file, and the file 
gets included for all the flavor of OVMF builds. In its current form, 
GUID is defined for all the package.

thanks


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
  2021-11-01 14:25   ` Tom Lendacky
@ 2021-11-03 16:02   ` Daniel P. Berrangé
  2021-11-04 18:18     ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 29+ messages in thread
From: Daniel P. Berrangé @ 2021-11-03 16:02 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Dr. David Alan Gilbert, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Mon, Nov 01, 2021 at 10:21:34AM +0000, Dov Murik wrote:
> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> for measured linux boot", 2021-09-30) introduced measured direct boot
> with -kernel, using an OVMF-designated hashes table which QEMU fills.
> 
> However, if OVMF doesn't designate such an area, QEMU would completely
> abort the VM launch.  This breaks launching with -kernel using older
> OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
> 
> Instead, just warn the user that -kernel was supplied by OVMF doesn't
> specify the GUID for the hashes table.  The following warning will be
> displayed during VM launch:
> 
>     qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  target/i386/sev.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index eede07f11d..682b8ccf6c 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      int aligned_len;
>  
>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
> -        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
> +        warn_report("SEV: kernel specified but OVMF has no hash table guid");
>          return false;

I'm pretty wary of doing this kind of thing.

If someone is using QEMU and they required to have the hashes populated
for their use case, they now don't get a fatal error if something goes
wrong with the process. This is bad as it hides a serious mistake.

If someone is using QEMU and they don't require to have the hashes
populated and they knowingly use a firmware that doesn't support
this, they'll now get a irrelevant warning every time they boot
QEMU. This is bad because IME users will file bugs complaining
about this bogus warning.


If we genuinely need to support both uses cases, then we should have
an explicit command line flag to request the desired behaviour.

This could be a -machine option to indicate that the hashes must
be populated.

 - unset: try to populate hashes, *silently* ignore missing table
          in ovmf
 - set == on: try to populate hashes, report error on missing
             table in ovmf
  -set == off: never try to populate hashes, nor look for the
               table in ovmf

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-01 10:21 ` [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area Dov Murik
  2021-11-02 12:36   ` Dr. David Alan Gilbert
@ 2021-11-03 16:07   ` Daniel P. Berrangé
  2021-11-05  7:52     ` Dov Murik
  1 sibling, 1 reply; 29+ messages in thread
From: Daniel P. Berrangé @ 2021-11-03 16:07 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Dr. David Alan Gilbert, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Mon, Nov 01, 2021 at 10:21:35AM +0000, Dov Murik wrote:
> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> for measured linux boot", 2021-09-30) introduced measured direct boot
> with -kernel, using an OVMF-designated hashes table which QEMU fills.
> 
> However, no checks are performed on the validity of the hashes area
> designated by OVMF.  Specifically, if OVMF publishes the
> SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
> cause QEMU to write the hashes entries over the first page of the
> guest's memory (GPA 0).
> 
> Add validity checks to the published area.  If the hashes table area's
> base address is zero, or its size is too small to fit the aligned hashes
> table, warn and skip the hashes entries addition.  In such case, the
> following warning will be displayed:
> 
>     qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)
> 
> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> Reported-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  target/i386/sev.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index 682b8ccf6c..a20ddb545e 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>      uint8_t kernel_hash[HASH_SIZE];
>      uint8_t *hashp;
>      size_t hash_len = HASH_SIZE;
> -    int aligned_len;
> +    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
>  
>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
>          return false;
>      }
>      area = (SevHashTableDescriptor *)data;
> +    if (!area->base || area->size < aligned_len) {
> +        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
> +                    area->base, area->size);
> +        return false;
> +    }

I think warn_report is likely a bad idea.

If someone's use case is relying on the hashs being populated, then
we need to be able to error_report and exit, not carry on with a
known broken setup.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-02 13:22   ` Dov Murik
  2021-11-02 14:48     ` Brijesh Singh
@ 2021-11-03 16:10     ` Daniel P. Berrangé
  1 sibling, 0 replies; 29+ messages in thread
From: Daniel P. Berrangé @ 2021-11-03 16:10 UTC (permalink / raw)
  To: Dov Murik
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Dr. David Alan Gilbert, Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Tue, Nov 02, 2021 at 03:22:24PM +0200, Dov Murik wrote:
> 
> 
> On 02/11/2021 12:52, Brijesh Singh wrote:
> > Hi Dov,
> > 
> > Overall the patch looks good, only question I have is that now we are
> > enforce qemu to hash the kernel, initrd and cmdline unconditionally for
> > any of the SEV guest launches. This requires anyone wanting to
> > calculating the expected measurement need to account for it. Should we
> > make the hash page build optional ?
> > 
> 
> The problem with adding a -enable-add-kernel-hashes QEMU option (or
> suboption) is yet another complexity for the user.

I don't view that as complexity - rather it is the user being explicit
about what their requirements are. If they ask for the kernel hashes
and we can't honour that, we can now give them a clear error and
exit instead of carrying on with a broken setup.

If they don't ask for kernel hashes, we can skip the whole bit and
not have a problem with bogus warnings or back compatibilty worries.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-03 16:02   ` Daniel P. Berrangé
@ 2021-11-04 18:18     ` Dr. David Alan Gilbert
  2021-11-04 18:22       ` Daniel P. Berrangé
  0 siblings, 1 reply; 29+ messages in thread
From: Dr. David Alan Gilbert @ 2021-11-04 18:18 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Daniel P. Berrangé (berrange@redhat.com) wrote:
> On Mon, Nov 01, 2021 at 10:21:34AM +0000, Dov Murik wrote:
> > Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> > for measured linux boot", 2021-09-30) introduced measured direct boot
> > with -kernel, using an OVMF-designated hashes table which QEMU fills.
> > 
> > However, if OVMF doesn't designate such an area, QEMU would completely
> > abort the VM launch.  This breaks launching with -kernel using older
> > OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
> > 
> > Instead, just warn the user that -kernel was supplied by OVMF doesn't
> > specify the GUID for the hashes table.  The following warning will be
> > displayed during VM launch:
> > 
> >     qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid
> > 
> > Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> > Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
> > ---
> >  target/i386/sev.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/target/i386/sev.c b/target/i386/sev.c
> > index eede07f11d..682b8ccf6c 100644
> > --- a/target/i386/sev.c
> > +++ b/target/i386/sev.c
> > @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
> >      int aligned_len;
> >  
> >      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
> > -        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
> > +        warn_report("SEV: kernel specified but OVMF has no hash table guid");
> >          return false;
> 
> I'm pretty wary of doing this kind of thing.
> 
> If someone is using QEMU and they required to have the hashes populated
> for their use case, they now don't get a fatal error if something goes
> wrong with the process. This is bad as it hides a serious mistake.
> 
> If someone is using QEMU and they don't require to have the hashes
> populated and they knowingly use a firmware that doesn't support
> this, they'll now get a irrelevant warning every time they boot
> QEMU. This is bad because IME users will file bugs complaining
> about this bogus warning.
> 
> 
> If we genuinely need to support both uses cases, then we should have
> an explicit command line flag to request the desired behaviour.
> 
> This could be a -machine option to indicate that the hashes must
> be populated.
> 
>  - unset: try to populate hashes, *silently* ignore missing table
>           in ovmf
>  - set == on: try to populate hashes, report error on missing
>              table in ovmf
>   -set == off: never try to populate hashes, nor look for the
>                table in ovmf

Or as a property on the sev-guest object.

Dave

> Regards,
> Daniel
> -- 
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-04 18:18     ` Dr. David Alan Gilbert
@ 2021-11-04 18:22       ` Daniel P. Berrangé
  2021-11-05  7:41         ` Dov Murik
  0 siblings, 1 reply; 29+ messages in thread
From: Daniel P. Berrangé @ 2021-11-04 18:22 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Thu, Nov 04, 2021 at 06:18:10PM +0000, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berrange@redhat.com) wrote:
> > On Mon, Nov 01, 2021 at 10:21:34AM +0000, Dov Murik wrote:
> > > Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
> > > for measured linux boot", 2021-09-30) introduced measured direct boot
> > > with -kernel, using an OVMF-designated hashes table which QEMU fills.
> > > 
> > > However, if OVMF doesn't designate such an area, QEMU would completely
> > > abort the VM launch.  This breaks launching with -kernel using older
> > > OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
> > > 
> > > Instead, just warn the user that -kernel was supplied by OVMF doesn't
> > > specify the GUID for the hashes table.  The following warning will be
> > > displayed during VM launch:
> > > 
> > >     qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid
> > > 
> > > Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
> > > Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
> > > ---
> > >  target/i386/sev.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/target/i386/sev.c b/target/i386/sev.c
> > > index eede07f11d..682b8ccf6c 100644
> > > --- a/target/i386/sev.c
> > > +++ b/target/i386/sev.c
> > > @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
> > >      int aligned_len;
> > >  
> > >      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
> > > -        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
> > > +        warn_report("SEV: kernel specified but OVMF has no hash table guid");
> > >          return false;
> > 
> > I'm pretty wary of doing this kind of thing.
> > 
> > If someone is using QEMU and they required to have the hashes populated
> > for their use case, they now don't get a fatal error if something goes
> > wrong with the process. This is bad as it hides a serious mistake.
> > 
> > If someone is using QEMU and they don't require to have the hashes
> > populated and they knowingly use a firmware that doesn't support
> > this, they'll now get a irrelevant warning every time they boot
> > QEMU. This is bad because IME users will file bugs complaining
> > about this bogus warning.
> > 
> > 
> > If we genuinely need to support both uses cases, then we should have
> > an explicit command line flag to request the desired behaviour.
> > 
> > This could be a -machine option to indicate that the hashes must
> > be populated.
> > 
> >  - unset: try to populate hashes, *silently* ignore missing table
> >           in ovmf
> >  - set == on: try to populate hashes, report error on missing
> >              table in ovmf
> >   -set == off: never try to populate hashes, nor look for the
> >                table in ovmf
> 
> Or as a property on the sev-guest object.

Yep, I thought of that too, and I'm pretty undecided which is "best".

-machine makes sense as 'kernel' and 'initrd' are properties of
the '-machine' and we're doing stuff related to the.

-object sev-guest makes sense as this is behaviour that's (currently)
specific to SEV.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-03 15:44         ` Brijesh Singh
@ 2021-11-05  7:38           ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-05  7:38 UTC (permalink / raw)
  To: Brijesh Singh, Dr. David Alan Gilbert, Daniel P. Berrangé
  Cc: Tom Lendacky, Ashish Kalra, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, qemu-devel, Dov Murik, Tobin Feldman-Fitzthum,
	Paolo Bonzini, Philippe Mathieu-Daudé



On 03/11/2021 17:44, Brijesh Singh wrote:
> 
> 
> On 11/3/21 9:08 AM, Dr. David Alan Gilbert wrote:
>> * Brijesh Singh (brijesh.singh@amd.com) wrote:
>>>
>>>
>>> On 11/2/21 8:22 AM, Dov Murik wrote:
>>>>
>>>>
>>>> On 02/11/2021 12:52, Brijesh Singh wrote:
>>>>> Hi Dov,
>>>>>
>>>>> Overall the patch looks good, only question I have is that now we are
>>>>> enforce qemu to hash the kernel, initrd and cmdline unconditionally
>>>>> for
>>>>> any of the SEV guest launches. This requires anyone wanting to
>>>>> calculating the expected measurement need to account for it. Should we
>>>>> make the hash page build optional ?
>>>>>
>>>>
>>>> The problem with adding a -enable-add-kernel-hashes QEMU option (or
>>>> suboption) is yet another complexity for the user.  I'd also argue that
>>>> adding these hashes can lead to a more secure VM boot process, so it
>>>> makes sense for it to be the default (and maybe introduce a
>>>> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
>>>> measurement from changing due to addition of hashes?).
>>>>
>>>> Maybe, on the other hand, OVMF should "report" whether it supports
>>>> hashes verification. If it does, it should have the GUID in the table
>>>> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
>>>> it doesn't support that, then the entry should not appear at all, and
>>>> then QEMU won't add the hashes (with patch 1 from this series).  This
>>>> means that in edk2 we need to remove the SEV Hash Table block from the
>>>> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
>>>>
>>>
>>> By leaving it ON is conveying a wrong message to the user. The
>>> library used
>>> for verifying the hash is a NULL library for all the builds of Ovmf
>>> except
>>> the AmdSev package. In the NULL library case, OVMF does not perform any
>>> checks and hash table is useless. I will raise this on concern on
>>> your Ovmf
>>> patch series.
>>>
>>> IMHO, if you want to turn it ON by default then make sure all the OVMF
>>> package builds supports validating the hash.
>>>
>>>
>>>> But the problem with this approach is that it prevents the future
>>>> unification of AmdSev and OvmfPkg, which is a possibility we discussed
>>>> (at least with Dave Gilbert), though not sure it's a good/feasible
>>>> goal.
>>>>
>>>>
>>>
>>> This is my exact concern, we are auto enabling the features in Qemu
>>> that is
>>> supported by AmdSev package only.
>>
>> I'm confused; wouldn't the trick be to only define the GUIDs for the
>> builds that support the validation?
>>
> 
> The GUID is hardcoded in the OVMF reset vector asm file, and the file
> gets included for all the flavor of OVMF builds. In its current form,
> GUID is defined for all the package.
> 

(We can overcome that by changing to a new GUID and modifying the reset
vector asm file to include the SEV hashes GUID only in the AmdSev build.
Requires changes both in OVMF and in QEMU.)

But some people want to use a non-hash-validating OVMF build with
-kernel (that's the "old OVMF" scenario that Tom presented).  In that case:

1. QEMU won't find the GUID, and will fail. This is breaking behaviour
for existing users.
2. If we just warn (as this patch suggested), then we don't enforce the
secure behaviour that some users want.

Following Daniel's suggestion, I think I'm going to send another round
in which the whole kernel hashes addition will happen only if the user
explicitly requested:

  -object sev_guest,id=sev0,...,kernel_hashes=on

With the default being 'off'.

(and change the warn_report above to error_report so they are fatal.)

This is basically keeping the new functionality for the release under a
feature flag, so users that want to use it will enable it explicitly and
all other users have the same behaviour as in previous releases.


As Daniel mentioned, we can also consider an 'auto' mode in which we add
the kernel hashes only if the GUID exists in OVMF, but I actually came
to an understanding that this is too confusing in the state of OVMF
builds right now.

Users that use the tighter OVMF build (AmdSev) will get a boot failure
from OVMF if they don't define kernel_hashes=on, so that won't be
accidentally missed.



-Dov



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
  2021-11-04 18:22       ` Daniel P. Berrangé
@ 2021-11-05  7:41         ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-05  7:41 UTC (permalink / raw)
  To: Daniel P. Berrangé, Dr. David Alan Gilbert
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 04/11/2021 20:22, Daniel P. Berrangé wrote:
> On Thu, Nov 04, 2021 at 06:18:10PM +0000, Dr. David Alan Gilbert wrote:
>> * Daniel P. Berrangé (berrange@redhat.com) wrote:
>>> On Mon, Nov 01, 2021 at 10:21:34AM +0000, Dov Murik wrote:
>>>> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
>>>> for measured linux boot", 2021-09-30) introduced measured direct boot
>>>> with -kernel, using an OVMF-designated hashes table which QEMU fills.
>>>>
>>>> However, if OVMF doesn't designate such an area, QEMU would completely
>>>> abort the VM launch.  This breaks launching with -kernel using older
>>>> OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID.
>>>>
>>>> Instead, just warn the user that -kernel was supplied by OVMF doesn't
>>>> specify the GUID for the hashes table.  The following warning will be
>>>> displayed during VM launch:
>>>>
>>>>     qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid
>>>>
>>>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
>>>> Reported-by: Tom Lendacky <thomas.lendacky@amd.com>
>>>> ---
>>>>  target/i386/sev.c | 2 +-
>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/target/i386/sev.c b/target/i386/sev.c
>>>> index eede07f11d..682b8ccf6c 100644
>>>> --- a/target/i386/sev.c
>>>> +++ b/target/i386/sev.c
>>>> @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>>>>      int aligned_len;
>>>>  
>>>>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>>>> -        error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
>>>> +        warn_report("SEV: kernel specified but OVMF has no hash table guid");
>>>>          return false;
>>>
>>> I'm pretty wary of doing this kind of thing.
>>>
>>> If someone is using QEMU and they required to have the hashes populated
>>> for their use case, they now don't get a fatal error if something goes
>>> wrong with the process. This is bad as it hides a serious mistake.
>>>
>>> If someone is using QEMU and they don't require to have the hashes
>>> populated and they knowingly use a firmware that doesn't support
>>> this, they'll now get a irrelevant warning every time they boot
>>> QEMU. This is bad because IME users will file bugs complaining
>>> about this bogus warning.
>>>
>>>
>>> If we genuinely need to support both uses cases, then we should have
>>> an explicit command line flag to request the desired behaviour.
>>>
>>> This could be a -machine option to indicate that the hashes must
>>> be populated.
>>>
>>>  - unset: try to populate hashes, *silently* ignore missing table
>>>           in ovmf
>>>  - set == on: try to populate hashes, report error on missing
>>>              table in ovmf
>>>   -set == off: never try to populate hashes, nor look for the
>>>                table in ovmf
>>
>> Or as a property on the sev-guest object.
> 
> Yep, I thought of that too, and I'm pretty undecided which is "best".
> 
> -machine makes sense as 'kernel' and 'initrd' are properties of
> the '-machine' and we're doing stuff related to the.
> 
> -object sev-guest makes sense as this is behaviour that's (currently)
> specific to SEV.

Thanks for the suggestions.

I'm going to go with '-object sev-guest,...,kernel_hashes=on' because
this whole function is defined in sev.c and only works with the AmdSev
OVMF target.

-Dov


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
  2021-11-03 16:07   ` Daniel P. Berrangé
@ 2021-11-05  7:52     ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-05  7:52 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Marcelo Tosatti, qemu-devel,
	Dr. David Alan Gilbert, Dov Murik, Tobin Feldman-Fitzthum,
	Paolo Bonzini, Philippe Mathieu-Daudé



On 03/11/2021 18:07, Daniel P. Berrangé wrote:
> On Mon, Nov 01, 2021 at 10:21:35AM +0000, Dov Murik wrote:
>> Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes
>> for measured linux boot", 2021-09-30) introduced measured direct boot
>> with -kernel, using an OVMF-designated hashes table which QEMU fills.
>>
>> However, no checks are performed on the validity of the hashes area
>> designated by OVMF.  Specifically, if OVMF publishes the
>> SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will
>> cause QEMU to write the hashes entries over the first page of the
>> guest's memory (GPA 0).
>>
>> Add validity checks to the published area.  If the hashes table area's
>> base address is zero, or its size is too small to fit the aligned hashes
>> table, warn and skip the hashes entries addition.  In such case, the
>> following warning will be displayed:
>>
>>     qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0)
>>
>> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
>> Reported-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  target/i386/sev.c | 8 ++++++--
>>  1 file changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/target/i386/sev.c b/target/i386/sev.c
>> index 682b8ccf6c..a20ddb545e 100644
>> --- a/target/i386/sev.c
>> +++ b/target/i386/sev.c
>> @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
>>      uint8_t kernel_hash[HASH_SIZE];
>>      uint8_t *hashp;
>>      size_t hash_len = HASH_SIZE;
>> -    int aligned_len;
>> +    int aligned_len = ROUND_UP(sizeof(SevHashTable), 16);
>>  
>>      if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
>>          warn_report("SEV: kernel specified but OVMF has no hash table guid");
>>          return false;
>>      }
>>      area = (SevHashTableDescriptor *)data;
>> +    if (!area->base || area->size < aligned_len) {
>> +        warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)",
>> +                    area->base, area->size);
>> +        return false;
>> +    }
> 
> I think warn_report is likely a bad idea.
> 
> If someone's use case is relying on the hashs being populated, then
> we need to be able to error_report and exit, not carry on with a
> known broken setup.
> 

Thanks you.  As I wrote elsewhere, I will put the whole thing under a
flag of sev-guest.  If the flag is ON then I will error_report and exit
if the GUID is missing or if the address/size is wrong, as you suggest.

-Dov


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-02 14:48     ` Brijesh Singh
  2021-11-03 14:08       ` Dr. David Alan Gilbert
@ 2021-11-05 18:32       ` Dov Murik
  2021-11-08 21:22         ` Brijesh Singh
  1 sibling, 1 reply; 29+ messages in thread
From: Dov Murik @ 2021-11-05 18:32 UTC (permalink / raw)
  To: Brijesh Singh, qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, Dr. David Alan Gilbert, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 02/11/2021 16:48, Brijesh Singh wrote:
> 
> 
> On 11/2/21 8:22 AM, Dov Murik wrote:
>>
>>
>> On 02/11/2021 12:52, Brijesh Singh wrote:
>>> Hi Dov,
>>>
>>> Overall the patch looks good, only question I have is that now we are
>>> enforce qemu to hash the kernel, initrd and cmdline unconditionally for
>>> any of the SEV guest launches. This requires anyone wanting to
>>> calculating the expected measurement need to account for it. Should we
>>> make the hash page build optional ?
>>>
>>
>> The problem with adding a -enable-add-kernel-hashes QEMU option (or
>> suboption) is yet another complexity for the user.  I'd also argue that
>> adding these hashes can lead to a more secure VM boot process, so it
>> makes sense for it to be the default (and maybe introduce a
>> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
>> measurement from changing due to addition of hashes?).
>>
>> Maybe, on the other hand, OVMF should "report" whether it supports
>> hashes verification. If it does, it should have the GUID in the table
>> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
>> it doesn't support that, then the entry should not appear at all, and
>> then QEMU won't add the hashes (with patch 1 from this series).  This
>> means that in edk2 we need to remove the SEV Hash Table block from the
>> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
>>
> 
> By leaving it ON is conveying a wrong message to the user. The library
> used for verifying the hash is a NULL library for all the builds of Ovmf
> except the AmdSev package. In the NULL library case, OVMF does not
> perform any checks and hash table is useless. I will raise this on
> concern on your Ovmf patch series.
> 
> IMHO, if you want to turn it ON by default then make sure all the OVMF
> package builds supports validating the hash.
> 
> 
>> But the problem with this approach is that it prevents the future
>> unification of AmdSev and OvmfPkg, which is a possibility we discussed
>> (at least with Dave Gilbert), though not sure it's a good/feasible goal.
>>
>>
> 
> This is my exact concern, we are auto enabling the features in Qemu that
> is supported by AmdSev package only.
> 
> 
>>
>>> I am thinking this more for the SEV-SNP guest. As you may be aware that
>>> with SEV-SNP the attestation is performed by the guest, and its possible
>>> for the launch flow to pass 512-bits of host_data that gets included in
>>> the report. If a user wants to do the hash'e checks for the SNP then
>>> they can pass a hash of kernel, initrd and cmdline through a
>>> launch_finish.ID_BLOCK.host_data and does not require a special hash
>>> page. This it will simplify the expected hash calculation.
>>
>> That is a new measured boot "protocol" that we can discuss, and see
>> whether it's better/easier than the existing one at hand that works on
>> SEV and SEV-ES.
>>
>> What I don't understand in your suggestion is who performs a SHA256 of
>> the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
>> (though ideally earlier is better).  Can you describe the details
>> (step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
>> the measurement/attestation is performed?
>>
>>
> 
> There are a multiple ways on how you can do a measured boot with the SNP.
> 
> 1) VMPL0 (SVSM) can provide a complete vTPM (see the MSFT proposal on
> SNP mailing list).
> 
> 2) Use your existing hashing approach with some changes to provide a bit
> more flexibility.
> 
> 3) Use your existing hashing approach but zero out the hash page when
> -kernel is not used.
> 
> Let me expand #2.
> 
> While launching the SNP guest, a guest owner can provide a ID block that
> KVM will pass to the PSP during the guest launch flow. In the ID block
> there is a field called "host_data". A guest owner can do a hash of
> kernel/initrd/cmdline and include it in the "host_data" field. During
> the hash verification, the OVMF can call the SNP_GET_REPORT. The PSP
> will includes the "host_data" passed in the launch process in the report
> and OVMF can use it for the verification. Unlike the current
> implementation, this enables a guest owner to provides the hash without
> requiring any changes in the Qemu and thus affecting the measurement.
> 

Is there a way (in the current NP patches for OVMF) for OVMF to call
SNP_GET_REPORT? Or is this something we need to add support for? Will it
mess up the sequence numbers that are later going to be used by the
kernel as well when managing SNP guest requests?



> One thing to note that both #2 and #3 requires ovmf to connect to guest
> owner to validate the report before using the "host_data" or "hash page".
> 

For direct boot (with -kernel/-initrd), I don't understand why OVMF
needs to contact the GO.  If OVMF can fetch the host_data field, and use
that to verify the blobs delivered from QEMU via fw_cfg, it should be
enough.

Later in userspace a user program will contact the GO with the
attestation report (which measures host_data and the OVMF memory). If
the measurement is not what the GO expects, then it won't release the
secret (which should be necessary for the actual meaningful workload
performed in the guest).


This should mitigate the following attacks:

1. Rogue CSP replaces OVMF with a rogue-OVMF that doesn't actually check
the hashes (the GO won't release the secret due to wrong measurement in
attestation report).
2. Rogue CSP uses "good" host_data content (kernel hash) but delivers
malicious kernel via fw_cfg (stopped by OVMF verifying the hashes).
3. Rogue CSP uses malicious kernel and its hashes in host_data (the GO
won't release the secret due to wrong host_data in attestation report).


-Dov


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-05 18:32       ` Dov Murik
@ 2021-11-08 21:22         ` Brijesh Singh
  2021-11-09  7:34           ` Dov Murik
  0 siblings, 1 reply; 29+ messages in thread
From: Brijesh Singh @ 2021-11-08 21:22 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: brijesh.singh, Paolo Bonzini, Marcelo Tosatti,
	Dr. David Alan Gilbert, Eduardo Habkost,
	Philippe Mathieu-Daudé,
	Ashish Kalra, Tom Lendacky, Tobin Feldman-Fitzthum,
	James Bottomley



On 11/5/21 1:32 PM, Dov Murik wrote:
> 
> 
> On 02/11/2021 16:48, Brijesh Singh wrote:
>>
>>
>> On 11/2/21 8:22 AM, Dov Murik wrote:
>>>
>>>
>>> On 02/11/2021 12:52, Brijesh Singh wrote:
>>>> Hi Dov,
>>>>
>>>> Overall the patch looks good, only question I have is that now we are
>>>> enforce qemu to hash the kernel, initrd and cmdline unconditionally for
>>>> any of the SEV guest launches. This requires anyone wanting to
>>>> calculating the expected measurement need to account for it. Should we
>>>> make the hash page build optional ?
>>>>
>>>
>>> The problem with adding a -enable-add-kernel-hashes QEMU option (or
>>> suboption) is yet another complexity for the user.  I'd also argue that
>>> adding these hashes can lead to a more secure VM boot process, so it
>>> makes sense for it to be the default (and maybe introduce a
>>> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
>>> measurement from changing due to addition of hashes?).
>>>
>>> Maybe, on the other hand, OVMF should "report" whether it supports
>>> hashes verification. If it does, it should have the GUID in the table
>>> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
>>> it doesn't support that, then the entry should not appear at all, and
>>> then QEMU won't add the hashes (with patch 1 from this series).  This
>>> means that in edk2 we need to remove the SEV Hash Table block from the
>>> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
>>>
>>
>> By leaving it ON is conveying a wrong message to the user. The library
>> used for verifying the hash is a NULL library for all the builds of Ovmf
>> except the AmdSev package. In the NULL library case, OVMF does not
>> perform any checks and hash table is useless. I will raise this on
>> concern on your Ovmf patch series.
>>
>> IMHO, if you want to turn it ON by default then make sure all the OVMF
>> package builds supports validating the hash.
>>
>>
>>> But the problem with this approach is that it prevents the future
>>> unification of AmdSev and OvmfPkg, which is a possibility we discussed
>>> (at least with Dave Gilbert), though not sure it's a good/feasible goal.
>>>
>>>
>>
>> This is my exact concern, we are auto enabling the features in Qemu that
>> is supported by AmdSev package only.
>>
>>
>>>
>>>> I am thinking this more for the SEV-SNP guest. As you may be aware that
>>>> with SEV-SNP the attestation is performed by the guest, and its possible
>>>> for the launch flow to pass 512-bits of host_data that gets included in
>>>> the report. If a user wants to do the hash'e checks for the SNP then
>>>> they can pass a hash of kernel, initrd and cmdline through a
>>>> launch_finish.ID_BLOCK.host_data and does not require a special hash
>>>> page. This it will simplify the expected hash calculation.
>>>
>>> That is a new measured boot "protocol" that we can discuss, and see
>>> whether it's better/easier than the existing one at hand that works on
>>> SEV and SEV-ES.
>>>
>>> What I don't understand in your suggestion is who performs a SHA256 of
>>> the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
>>> (though ideally earlier is better).  Can you describe the details
>>> (step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
>>> the measurement/attestation is performed?
>>>
>>>
>>
>> There are a multiple ways on how you can do a measured boot with the SNP.
>>
>> 1) VMPL0 (SVSM) can provide a complete vTPM (see the MSFT proposal on
>> SNP mailing list).
>>
>> 2) Use your existing hashing approach with some changes to provide a bit
>> more flexibility.
>>
>> 3) Use your existing hashing approach but zero out the hash page when
>> -kernel is not used.
>>
>> Let me expand #2.
>>
>> While launching the SNP guest, a guest owner can provide a ID block that
>> KVM will pass to the PSP during the guest launch flow. In the ID block
>> there is a field called "host_data". A guest owner can do a hash of
>> kernel/initrd/cmdline and include it in the "host_data" field. During
>> the hash verification, the OVMF can call the SNP_GET_REPORT. The PSP
>> will includes the "host_data" passed in the launch process in the report
>> and OVMF can use it for the verification. Unlike the current
>> implementation, this enables a guest owner to provides the hash without
>> requiring any changes in the Qemu and thus affecting the measurement.
>>
> 
> Is there a way (in the current NP patches for OVMF) for OVMF to call
> SNP_GET_REPORT? Or is this something we need to add support for? Will it
> mess up the sequence numbers that are later going to be used by the
> kernel as well when managing SNP guest requests?
> 
> 

The current OVMF patches does not add a library to query the attestation 
report yet. If required it should be possible to add such a libraries. 
The VMGEXIT is available to both Guest OS and Guest BIOS. The sequence 
number should not be an issue. As per the GHCB spec, the guest BIOS will 
save the sequence number in the secrets page reserved area and guest 
kernel can picked the next number from that region (its same as the 
kexec approach).

> 
>> One thing to note that both #2 and #3 requires ovmf to connect to guest
>> owner to validate the report before using the "host_data" or "hash page".
>>
> 
> For direct boot (with -kernel/-initrd), I don't understand why OVMF
> needs to contact the GO.  If OVMF can fetch the host_data field, and use
> that to verify the blobs delivered from QEMU via fw_cfg, it should be
> enough.
>

Well, I am trying to match with the current model in which the Hash's 
are provided through the secrets injection for the comparision. In other 
words, the attestation is completed before OVMF does the hash 
comparison. So, if you want to have the same security property then you 
need to perform the attestation before comparing the hash'es because a 
malicious HV may bypass the guid check.

thanks

> Later in userspace a user program will contact the GO with the
> attestation report (which measures host_data and the OVMF memory). If
> the measurement is not what the GO expects, then it won't release the
> secret (which should be necessary for the actual meaningful workload
> performed in the guest).
> 
> 
> This should mitigate the following attacks:
> 
> 1. Rogue CSP replaces OVMF with a rogue-OVMF that doesn't actually check
> the hashes (the GO won't release the secret due to wrong measurement in
> attestation report).
> 2. Rogue CSP uses "good" host_data content (kernel hash) but delivers
> malicious kernel via fw_cfg (stopped by OVMF verifying the hashes).
> 3. Rogue CSP uses malicious kernel and its hashes in host_data (the GO
> won't release the secret due to wrong host_data in attestation report).
> 
> 
> -Dov
> 


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
  2021-11-08 21:22         ` Brijesh Singh
@ 2021-11-09  7:34           ` Dov Murik
  0 siblings, 0 replies; 29+ messages in thread
From: Dov Murik @ 2021-11-09  7:34 UTC (permalink / raw)
  To: Brijesh Singh, qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Eduardo Habkost, James Bottomley,
	Marcelo Tosatti, Dr. David Alan Gilbert, Dov Murik,
	Tobin Feldman-Fitzthum, Paolo Bonzini,
	Philippe Mathieu-Daudé



On 08/11/2021 23:22, Brijesh Singh wrote:
> 
> 
> On 11/5/21 1:32 PM, Dov Murik wrote:
>>
>>
>> On 02/11/2021 16:48, Brijesh Singh wrote:
>>>
>>>
>>> On 11/2/21 8:22 AM, Dov Murik wrote:
>>>>
>>>>
>>>> On 02/11/2021 12:52, Brijesh Singh wrote:
>>>>> Hi Dov,
>>>>>
>>>>> Overall the patch looks good, only question I have is that now we are
>>>>> enforce qemu to hash the kernel, initrd and cmdline unconditionally
>>>>> for
>>>>> any of the SEV guest launches. This requires anyone wanting to
>>>>> calculating the expected measurement need to account for it. Should we
>>>>> make the hash page build optional ?
>>>>>
>>>>
>>>> The problem with adding a -enable-add-kernel-hashes QEMU option (or
>>>> suboption) is yet another complexity for the user.  I'd also argue that
>>>> adding these hashes can lead to a more secure VM boot process, so it
>>>> makes sense for it to be the default (and maybe introduce a
>>>> -allow-insecure-unmeasured-kernel-via-fw-cfg option to prevent the
>>>> measurement from changing due to addition of hashes?).
>>>>
>>>> Maybe, on the other hand, OVMF should "report" whether it supports
>>>> hashes verification. If it does, it should have the GUID in the table
>>>> (near the reset vector), like the current OvmfPkg/AmdSev edk2 build. If
>>>> it doesn't support that, then the entry should not appear at all, and
>>>> then QEMU won't add the hashes (with patch 1 from this series).  This
>>>> means that in edk2 we need to remove the SEV Hash Table block from the
>>>> ResetVectorVtf0.asm for OvmfPkg, but include it in the AmdSev build.
>>>>
>>>
>>> By leaving it ON is conveying a wrong message to the user. The library
>>> used for verifying the hash is a NULL library for all the builds of Ovmf
>>> except the AmdSev package. In the NULL library case, OVMF does not
>>> perform any checks and hash table is useless. I will raise this on
>>> concern on your Ovmf patch series.
>>>
>>> IMHO, if you want to turn it ON by default then make sure all the OVMF
>>> package builds supports validating the hash.
>>>
>>>
>>>> But the problem with this approach is that it prevents the future
>>>> unification of AmdSev and OvmfPkg, which is a possibility we discussed
>>>> (at least with Dave Gilbert), though not sure it's a good/feasible
>>>> goal.
>>>>
>>>>
>>>
>>> This is my exact concern, we are auto enabling the features in Qemu that
>>> is supported by AmdSev package only.
>>>
>>>
>>>>
>>>>> I am thinking this more for the SEV-SNP guest. As you may be aware
>>>>> that
>>>>> with SEV-SNP the attestation is performed by the guest, and its
>>>>> possible
>>>>> for the launch flow to pass 512-bits of host_data that gets
>>>>> included in
>>>>> the report. If a user wants to do the hash'e checks for the SNP then
>>>>> they can pass a hash of kernel, initrd and cmdline through a
>>>>> launch_finish.ID_BLOCK.host_data and does not require a special hash
>>>>> page. This it will simplify the expected hash calculation.
>>>>
>>>> That is a new measured boot "protocol" that we can discuss, and see
>>>> whether it's better/easier than the existing one at hand that works on
>>>> SEV and SEV-ES.
>>>>
>>>> What I don't understand in your suggestion is who performs a SHA256 of
>>>> the fw_cfg blobs (kernel/initrd/cmdline) so they can later be verified
>>>> (though ideally earlier is better).  Can you describe the details
>>>> (step-by-step) of an SNP VM boot with -kernel/-initrd/-append and how
>>>> the measurement/attestation is performed?
>>>>
>>>>
>>>
>>> There are a multiple ways on how you can do a measured boot with the
>>> SNP.
>>>
>>> 1) VMPL0 (SVSM) can provide a complete vTPM (see the MSFT proposal on
>>> SNP mailing list).
>>>
>>> 2) Use your existing hashing approach with some changes to provide a bit
>>> more flexibility.
>>>
>>> 3) Use your existing hashing approach but zero out the hash page when
>>> -kernel is not used.
>>>
>>> Let me expand #2.
>>>
>>> While launching the SNP guest, a guest owner can provide a ID block that
>>> KVM will pass to the PSP during the guest launch flow. In the ID block
>>> there is a field called "host_data". A guest owner can do a hash of
>>> kernel/initrd/cmdline and include it in the "host_data" field. During
>>> the hash verification, the OVMF can call the SNP_GET_REPORT. The PSP
>>> will includes the "host_data" passed in the launch process in the report
>>> and OVMF can use it for the verification. Unlike the current
>>> implementation, this enables a guest owner to provides the hash without
>>> requiring any changes in the Qemu and thus affecting the measurement.
>>>
>>
>> Is there a way (in the current NP patches for OVMF) for OVMF to call
>> SNP_GET_REPORT? Or is this something we need to add support for? Will it
>> mess up the sequence numbers that are later going to be used by the
>> kernel as well when managing SNP guest requests?
>>
>>
> 
> The current OVMF patches does not add a library to query the attestation
> report yet. If required it should be possible to add such a libraries.
> The VMGEXIT is available to both Guest OS and Guest BIOS. The sequence
> number should not be an issue. As per the GHCB spec, the guest BIOS will
> save the sequence number in the secrets page reserved area and guest
> kernel can picked the next number from that region (its same as the
> kexec approach).
> 

OK, good to know. *If* we decide to use the host_data field to store the
hashes, then we would have to add the SNP_GET_REPORT functionality to OVMF.

>>
>>> One thing to note that both #2 and #3 requires ovmf to connect to guest
>>> owner to validate the report before using the "host_data" or "hash
>>> page".
>>>
>>
>> For direct boot (with -kernel/-initrd), I don't understand why OVMF
>> needs to contact the GO.  If OVMF can fetch the host_data field, and use
>> that to verify the blobs delivered from QEMU via fw_cfg, it should be
>> enough.
>>
> 
> Well, I am trying to match with the current model in which the Hash's
> are provided through the secrets injection for the comparision. In other
> words, the attestation is completed before OVMF does the hash
> comparison. So, if you want to have the same security property then you
> need to perform the attestation before comparing the hash'es because a
> malicious HV may bypass the guid check.
> 

In the current model (works for SEV and SEV-ES) the hashes are not
provided via secret injection; they are added by QEMU to the designated
hashes area in the guest.

If we only need the secret later (in userspace) then we can use a
similar model.  Hashes are either (a) added to the designated page (by
QEMU), or (b) passed in host_data (by QEMU).  OVMF fetch the hashes: (a)
by reading a memory page, or (b) by using SNP_GET_REPORT.  It will
verify them against the blobs from fw_cfg, and will continue to boot
only if they match.

and then it continues as I previously wrote:

> 
>> Later in userspace a user program will contact the GO with the
>> attestation report (which measures host_data and the OVMF memory). If
>> the measurement is not what the GO expects, then it won't release the
>> secret (which should be necessary for the actual meaningful workload
>> performed in the guest).
>>
>>
>> This should mitigate the following attacks:
>>
>> 1. Rogue CSP replaces OVMF with a rogue-OVMF that doesn't actually check
>> the hashes (the GO won't release the secret due to wrong measurement in
>> attestation report).
>> 2. Rogue CSP uses "good" host_data content (kernel hash) but delivers
>> malicious kernel via fw_cfg (stopped by OVMF verifying the hashes).
>> 3. Rogue CSP uses malicious kernel and its hashes in host_data (the GO
>> won't release the secret due to wrong host_data in attestation report).
>>


-Dov





^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2021-11-09  7:38 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-01 10:21 [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Dov Murik
2021-11-01 10:21 ` [PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found Dov Murik
2021-11-01 14:25   ` Tom Lendacky
2021-11-01 17:56     ` Dov Murik
2021-11-03 16:02   ` Daniel P. Berrangé
2021-11-04 18:18     ` Dr. David Alan Gilbert
2021-11-04 18:22       ` Daniel P. Berrangé
2021-11-05  7:41         ` Dov Murik
2021-11-01 10:21 ` [PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area Dov Murik
2021-11-02 12:36   ` Dr. David Alan Gilbert
2021-11-02 12:56     ` Dov Murik
2021-11-02 18:38       ` Dr. David Alan Gilbert
2021-11-02 19:00         ` Philippe Mathieu-Daudé
2021-11-03 16:07   ` Daniel P. Berrangé
2021-11-05  7:52     ` Dov Murik
2021-11-01 10:21 ` [PATCH 3/3] sev/i386: Perform padding calculations at compile-time Dov Murik
2021-11-02 11:36   ` Dr. David Alan Gilbert
2021-11-02 11:50     ` Dov Murik
2021-11-03 14:49   ` Philippe Mathieu-Daudé
2021-11-02 10:52 ` [PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF Brijesh Singh
2021-11-02 13:22   ` Dov Murik
2021-11-02 14:48     ` Brijesh Singh
2021-11-03 14:08       ` Dr. David Alan Gilbert
2021-11-03 15:44         ` Brijesh Singh
2021-11-05  7:38           ` Dov Murik
2021-11-05 18:32       ` Dov Murik
2021-11-08 21:22         ` Brijesh Singh
2021-11-09  7:34           ` Dov Murik
2021-11-03 16:10     ` Daniel P. Berrangé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).