Date   

[RFC PATCH v5 09/28] OvmfPkg/ResetVector: check the vmpl level

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Virtual Machine Privilege Level (VMPL) is an optional feature in the
SEV-SNP architecture, which allows a guest VM to divide its address space
into four levels. The level can be used to provide the hardware isolated
abstraction layers with a VM. The VMPL0 is the highest privilege, and
VMPL3 is the least privilege. Certain operations must be done by the VMPL0
software, such as:

* Validate or invalidate memory range (PVALIDATE instruction)
* Allocate VMSA page (RMPADJUST instruction when VMSA=1)

The initial SEV-SNP support assumes that it's running on VMPL0. Let's add
a check to make sure that we are running at VMPL0 before continuing the
boot. There is no easy method to query the current VMPL level. One simple
approach is to call PVALIDATE instruction and if the instruction causes
a #GP then its SEV-SNP guest is not booted under VMPL0. See the AMD APL
volume 3 (PVALIDATE) for additional information on the PVALIDATE.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/ResetVector/Ia32/AmdSev.asm | 89 ++++++++++++++++++++++++++++-
1 file changed, 87 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index b6f33d049a43..a9101ca8b8b2 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -53,6 +53,12 @@ BITS 32
; Hypervisor does not support SEV-SNP feature
%define TERM_HV_UNSUPPORTED_FEATURE 4

+; SEV-SNP guest is not launched at VMPL-0
+%define TERM_SNP_NOT_VMPL0 5
+
+; The #VC is not for PVALIDATE
+%define TERM_VC_NOT_PVALIDATE 6
+
; GHCB SEV Information MSR protocol
%define GHCB_SEV_INFORMATION_REQUEST 2
%define GHCB_SEV_INFORMATION_RESPONSE 1
@@ -139,6 +145,25 @@ BITS 32
SevEsUnexpectedRespTerminate:
TerminateVmgExit TERM_UNEXPECTED_RESP_CODE

+; Check whether we're booted under the VMPL-0.
+;
+; There is no straightforward way to query the current VMPL level. The simplest
+; method is to use the PVALIDATE instruction to change the page state. If its
+; not a VMPL-0 guest then PVALIDATE will cause #GP.
+;
+CheckSnpVmpl0:
+ ; This routine is part of the ROM, and should have been validated by the SNP
+ ; guest launch sequence. So its safe to re-validate the page containing
+ ; this routine.
+ mov eax, ADDR_OF(CheckSnpVmpl0)
+ mov ecx, 0
+ mov edx, 1
+ PVALIDATE
+
+ ; We will reach here only if we are running at VMPL-0.
+
+ OneTimeCallRet CheckSnpVmpl0
+
; Check if Secure Encrypted Virtualization (SEV) features are enabled.
;
; Register usage is tight in this routine, so multiple calls for the
@@ -193,6 +218,17 @@ CheckSevFeatures:
bt eax, 0
jnc NoSev

+ ; Check if we're SEV-SNP guest and booted under VMPL-0.
+ ;
+ ; This check should happen here because the PVALIDATE instruction
+ ; used in the check will cause an exception. The IDT is active
+ ; during the CheckSevFeatures only.
+ ;
+ bt eax, 2
+ jnc SkipCheckSnpVmpl0
+ OneTimeCall CheckSnpVmpl0
+
+SkipCheckSnpVmpl0:
; Check for SEV-ES memory encryption feature:
; CPUID Fn8000_001F[EAX] - Bit 3
; CPUID raises a #VC exception if running as an SEV-ES guest
@@ -393,6 +429,36 @@ IsSevEsEnabled:
SevEsDisabled:
OneTimeCallRet IsSevEsEnabled

+; Start handling of #GP exception handling routines
+;
+SevEsIdtNotPvalidate:
+ TerminateVmgExit TERM_VC_NOT_PVALIDATE
+ iret
+
+SevSnpGpException:
+ ;
+ ; If we're here, then we are an SEV-SNP guest and this
+ ; was triggered by a PVALIDATE instruction.
+ ;
+ ; Verify that its an PVALIDATE instruction
+ ; The exception stack looks like this:
+ ; +---------+
+ ; | .... |
+ ; | eip |
+ ; | err code|
+ ; +---------+
+ pop ebx
+ pop ebx
+ mov ecx, [ebx]
+ cmp ecx, 0xff010ff2 ; Compare EIP with PVALIDATE menomics
+ jne SevEsIdtNotPvalidate
+
+ ; The #GP was triggered by the PVALIDATE instruction, this will happen
+ ; only when we're not running at VMPL-0
+ ;
+ TerminateVmgExit TERM_SNP_NOT_VMPL0
+ iret
+
; Start of #VC exception handling routines
;

@@ -522,15 +588,34 @@ ALIGN 16
;
IDT_BASE:
;
-; Vectors 0 - 28 (No handlers)
+; Vectors 0 - 12 (No handlers)
;
-%rep 29
+%rep 13
dw 0 ; Offset low bits 15..0
dw 0x10 ; Selector
db 0 ; Reserved
db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
dw 0 ; Offset high bits 31..16
%endrep
+;
+; Vector 13 (GP Exception)
+;
+ dw (ADDR_OF(SevSnpGpException) & 0xffff) ; Offset low bits 15..0
+ dw 0x10 ; Selector
+ db 0 ; Reserved
+ db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+ dw (ADDR_OF(SevSnpGpException) >> 16) ; Offset high bits 31..16
+;
+; Vectors 14 - 28 (No handlers)
+;
+%rep 15
+ dw 0 ; Offset low bits 15..0
+ dw 0x10 ; Selector
+ db 0 ; Reserved
+ db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+ dw 0 ; Offset high bits 31..16
+%endrep
+
;
; Vector 29 (VMM Communication Exception)
;
--
2.17.1


[RFC PATCH v5 08/28] OvmfPkg/ResetVector: invalidate the GHCB page

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The GHCB page is part of a pre-validated memory range specified through
the SnpBootBlock GUID. When SEV-SNP is active, the GHCB page is
pre-validated by the hyperivosr during the SNP guest creation. On boot,
the reset vector maps the GHCB page as un-encrypted in the initial page
table. Just clearing the encryption attribute from the page table is not
enough. To maintain the security guarantees, the page must be invalidated.

The page invalidation consists of two steps:

1. Use the PVALIDATE instruction to clear Validated Bit from the RMP table.
2. Use the Page State Change VMGEXIT to ask hypervisor to change the page
state to shared in the RMP table.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/ResetVector/Ia32/AmdSev.asm | 125 ++++++++++++++++++++++
OvmfPkg/ResetVector/Ia32/PageTables64.asm | 13 +++
2 files changed, 138 insertions(+)

diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index c4c00056f9f3..b6f33d049a43 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -8,6 +8,8 @@
;
;------------------------------------------------------------------------------

+%include "Nasm.inc"
+
BITS 32

;
@@ -45,6 +47,25 @@ BITS 32
; The unexpected response code
%define TERM_UNEXPECTED_RESP_CODE 2

+; SNP page state change failure
+%define TERM_PAGE_STATE_CHANAGE 3
+
+; Hypervisor does not support SEV-SNP feature
+%define TERM_HV_UNSUPPORTED_FEATURE 4
+
+; GHCB SEV Information MSR protocol
+%define GHCB_SEV_INFORMATION_REQUEST 2
+%define GHCB_SEV_INFORMATION_RESPONSE 1
+
+; GHCB Page Invalidate request and response protocol values
+;
+%define GHCB_PAGE_STATE_CHANGE_REQUEST 20
+%define GHCB_PAGE_STATE_CHANGE_RESPONSE 21
+%define GHCB_PAGE_STATE_SHARED 2
+
+; GHCB Hypervisor features MSR protocol
+%define GHCB_HYPERVISOR_FEATURES_REQUEST 128
+%define GHCB_HYPERVISOR_FEATURES_RESPONSE 129

; Macro is used to issue the MSR protocol based VMGEXIT. The caller is
; responsible to populate values in the EDX:EAX registers. After the vmmcall
@@ -247,6 +268,110 @@ SevExit:

OneTimeCallRet CheckSevFeatures

+; The version 2 of GHCB specification added the support to query the hypervisor
+; features. If the GHCB version is >=2 then read the hypervisor features and
+; verify that SEV-SNP feature is supported.
+;
+CheckSnpHypervisorFeatures:
+ ; Get the SEV Information
+ xor eax, eax
+ xor edx, edx
+
+ VmgExit GHCB_SEV_INFORMATION_REQUEST, GHCB_SEV_INFORMATION_RESPONSE
+
+ ;
+ ; SEV Information Response GHCB MSR
+ ; GHCB_MSR[63:48] = Maximum protocol version
+ ; GHCB_MSR[47:32] = Minimum protocol version
+ ;
+ shr edx, 16
+ cmp edx, 2
+ jl SevSnpUnsupportedFeature
+
+ ; Get the hypervisor features
+ xor eax, eax
+ xor edx, edx
+
+ VmgExit GHCB_HYPERVISOR_FEATURES_REQUEST, GHCB_HYPERVISOR_FEATURES_RESPONSE
+
+ ;
+ ; Hypervisor features reponse
+ ; GHCB_MSR[63:12] = Features bitmap
+ ; BIT0 = SEV-SNP Supported
+ ;
+ shr eax, 12
+ bt eax, 0
+ jnc SevSnpUnsupportedFeature
+
+CheckSnpHypervisorFeaturesDone:
+ OneTimeCallRet CheckSnpHypervisorFeatures
+
+; If its an SEV-SNP guest then use the page state change VMGEXIT to invalidate
+; the GHCB page.
+;
+; Modified: EAX, EBX, ECX, EDX
+;
+InvalidateGHCBPage:
+ ; Check if SEV-SNP is enabled
+ ; MSR_0xC0010131 - Bit 2 (SEV-SNP enabled)
+ mov ecx, SEV_STATUS_MSR
+ rdmsr
+ bt eax, 2
+ jnc InvalidateGHCBPageDone
+
+ ; Verify that SEV-SNP feature is supported by the hypervisor.
+ OneTimeCall CheckSnpHypervisorFeatures
+
+ ; Use PVALIDATE instruction to invalidate the page
+ mov eax, GHCB_BASE
+ mov ecx, 0
+ mov edx, 0
+ PVALIDATE
+
+ ; Save the carry flag to be use later.
+ setc dl
+
+ ; If PVALIDATE fail then abort the launch.
+ cmp eax, 0
+ jne SevSnpPageStateFailureTerminate
+
+ ; Check the carry flag to determine if RMP entry was updated.
+ cmp dl, 0
+ jne SevSnpPageStateFailureTerminate
+
+ ; Ask hypervisor to change the page state to shared using the
+ ; Page State Change VMGEXIT.
+ ;
+ ; Setup GHCB MSR
+ ; GHCB_MSR[55:52] = Page Operation
+ ; GHCB_MSR[51:12] = Guest Physical Frame Number
+ ;
+ mov eax, (GHCB_BASE >> 12)
+ shl eax, 12
+ mov edx, (GHCB_PAGE_STATE_SHARED << 20)
+
+ VmgExit GHCB_PAGE_STATE_CHANGE_REQUEST, GHCB_PAGE_STATE_CHANGE_RESPONSE
+
+ ;
+ ; Response GHCB MSR
+ ; GHCB_MSR[63:12] = Error code
+ ;
+ cmp edx, 0
+ jnz SevSnpPageStateFailureTerminate
+
+InvalidateGHCBPageDone:
+ OneTimeCallRet InvalidateGHCBPage
+
+; Terminate the SEV-SNP guest due to the page state change failure
+SevSnpPageStateFailureTerminate:
+ TerminateVmgExit TERM_PAGE_STATE_CHANAGE
+
+; Terminate the SEV-SNP guest because hypervisor does not support
+; the SEV-SNP feature
+SevSnpUnsupportedFeature:
+ TerminateVmgExit TERM_HV_UNSUPPORTED_FEATURE
+
+
; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature
; is enabled.
;
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index eacdb69ddb9f..f587ef912e4c 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -140,6 +140,19 @@ clearGhcbMemoryLoop:
mov dword[ecx * 4 + GHCB_BASE - 4], eax
loop clearGhcbMemoryLoop

+ ;
+ ; The page table built above cleared the memory encryption mask from the
+ ; GHCB_BASE (aka made it shared). When SEV-SNP is enabled, to maintain
+ ; the security guarantees, the page state transition from private to
+ ; shared must go through the page invalidation steps. Invalidate the
+ ; memory range before loading the page table below.
+ ;
+ ; NOTE: the invalidation must happen after zeroing the GHCB memory. This
+ ; is because, in the 32-bit mode all the access are considered private.
+ ; The invalidation before the zero'ing will cause a #VC.
+ ;
+ OneTimeCall InvalidateGHCBPage
+
SetCr3:
;
; Set CR3 now that the paging structures are available
--
2.17.1


[RFC PATCH v5 07/28] OvmfPkg/ResetVector: pre-validate the data pages used in SEC phase

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

An SEV-SNP guest requires that private memory (aka pages mapped encrypted)
must be validated before being accessed.

The validation process consist of the following sequence:

1) Set the memory encryption attribute in the page table (aka C-bit).
Note: If the processor is in non-PAE mode, then all the memory accesses
are considered private.
2) Add the memory range as private in the RMP table. This can be performed
using the Page State Change VMGEXIT defined in the GHCB specification.
3) Use the PVALIDATE instruction to set the Validated Bit in the RMP table.

During the guest creation time, the VMM encrypts the OVMF_CODE.fd using
the SEV-SNP firmware provided LAUNCH_UPDATE_DATA command. In addition to
encrypting the content, the command also validates the memory region.
This allows us to execute the code without going through the validation
sequence.

During execution, the reset vector need to access some data pages
(such as page tables, SevESWorkarea, Sec stack). The data pages are
accessed as private memory. The data pages are not part of the
OVMF_CODE.fd, so they were not validated during the guest creation.

There are two approaches we can take to validate the data pages before
the access:

a) Enhance the OVMF reset vector code to validate the pages as described
above (go through step 2 - 3).
OR
b) Validate the pages during the guest creation time. The SEV firmware
provides a command which can be used by the VMM to validate the pages
without affecting the measurement of the launch.

Approach #b seems much simpler; it does not require any changes to the
OVMF reset vector code.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/OvmfPkg.dec | 5 +++++
OvmfPkg/OvmfPkgX64.fdf | 8 +++++++-
OvmfPkg/ResetVector/ResetVector.inf | 2 ++
OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 5 +++++
OvmfPkg/ResetVector/ResetVector.nasmb | 2 ++
5 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 93f759534ade..d0ec14ca2318 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -334,6 +334,11 @@ [PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|0|UINT32|0x49
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize|0|UINT32|0x50

+ ## The start and end of pre-validated memory region by the hypervisor
+ # through the SEV-SNP firmware.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart|0x0|UINT32|0x51
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd|0x0|UINT32|0x52
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 3e257aaf72bd..6bce3369e10d 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -105,7 +105,13 @@ [FD.MEMFD]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
FV = DXEFV

-################################################################################
+##########################################################################################
+#
+# The range of the pages pre-validated through the SEV-SNP firmware.
+#
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart = $(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd = $(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+##########################################################################################

[FV.SECFV]
FvNameGuid = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index 9a95d8687345..32206855193f 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -51,3 +51,5 @@ [FixedPcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedStart
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpHypervisorPreValidatedEnd
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index ecf1dbcc2caf..c5a062e69b26 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -57,9 +57,14 @@ guidedStructureStart:
; SEV-SNP boot block GUID and provide the GPA to the PSP to populate
; the memory area with the required information..
;
+; In order to boot the SEV-SNP guest the hypervisor must pre-validated the
+; memory range from SNP_HV_VALIDATED_START to SNP_HV_VALIDATED_END.
+;
; GUID (SEV-SNP boot block): bd39c0c2-2f8e-4243-83e8-1b74cebcb7d9
;
sevSnpBootBlockStart:
+ DD SNP_HV_VALIDATED_START
+ DD SNP_HV_VALIDATED_END
DD SNP_SECRETS_BASE
DD SNP_SECRETS_SIZE
DD SNP_CPUID_BASE
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 247f4eb0dc5e..645e949845f9 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -93,5 +93,7 @@
%define SNP_CPUID_SIZE FixedPcdGet32 (PcdOvmfSnpCpuidSize)
%define SNP_SECRETS_BASE FixedPcdGet32 (PcdOvmfSnpSecretsBase)
%define SNP_SECRETS_SIZE FixedPcdGet32 (PcdOvmfSnpSecretsSize)
+ %define SNP_HV_VALIDATED_START FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedStart)
+ %define SNP_HV_VALIDATED_END FixedPcdGet32 (PcdOvmfSnpHypervisorPreValidatedEnd)
%include "Ia16/ResetVectorVtf0.asm"

--
2.17.1


[RFC PATCH v5 06/28] OvmfPkg/ResetVector: introduce SEV-SNP boot block GUID

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Introduce a new SEV-SNP boot-specific GUID block. The block is used to
communicate the secrets and cpuid memory area reserved by the guest BIOS.
When SEV-SNP is enabled, the hypervisor will locate the SEV-SNP boot
block to get the location of the Secrets and CPUID page and call the
PSP firmware command to populate those memory areas.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/ResetVector/ResetVector.inf | 4 ++++
OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 22 ++++++++++++++++++++
OvmfPkg/ResetVector/ResetVector.nasmb | 4 ++++
3 files changed, 30 insertions(+)

diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index dc38f68919cd..9a95d8687345 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -47,3 +47,7 @@ [Pcd]
[FixedPcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index 9c0b5853a46f..ecf1dbcc2caf 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -47,6 +47,28 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0
;
guidedStructureStart:

+;
+; SEV-SNP boot support
+;
+; sevSnpBlock:
+; For the initial boot of SEV-SNP guest, a CPUID and Secrets page must
+; be reserved by the BIOS at a RAM area defined by SNP_CPUID_BASE and
+; SNP_SECRETS_BASE. A hypervisor will locate this information using the
+; SEV-SNP boot block GUID and provide the GPA to the PSP to populate
+; the memory area with the required information..
+;
+; GUID (SEV-SNP boot block): bd39c0c2-2f8e-4243-83e8-1b74cebcb7d9
+;
+sevSnpBootBlockStart:
+ DD SNP_SECRETS_BASE
+ DD SNP_SECRETS_SIZE
+ DD SNP_CPUID_BASE
+ DD SNP_CPUID_SIZE
+ DW sevSnpBootBlockEnd - sevSnpBootBlockStart
+ DB 0xC2, 0xC0, 0x39, 0xBD, 0x8e, 0x2F, 0x43, 0x42
+ DB 0x83, 0xE8, 0x1B, 0x74, 0xCE, 0xBC, 0xB7, 0xD9
+sevSnpBootBlockEnd:
+
;
; SEV Secret block
;
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 8a3269cfc212..247f4eb0dc5e 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -89,5 +89,9 @@
%define SEV_ES_AP_RESET_IP FixedPcdGet32 (PcdSevEsWorkAreaBase)
%define SEV_LAUNCH_SECRET_BASE FixedPcdGet32 (PcdSevLaunchSecretBase)
%define SEV_LAUNCH_SECRET_SIZE FixedPcdGet32 (PcdSevLaunchSecretSize)
+ %define SNP_CPUID_BASE FixedPcdGet32 (PcdOvmfSnpCpuidBase)
+ %define SNP_CPUID_SIZE FixedPcdGet32 (PcdOvmfSnpCpuidSize)
+ %define SNP_SECRETS_BASE FixedPcdGet32 (PcdOvmfSnpSecretsBase)
+ %define SNP_SECRETS_SIZE FixedPcdGet32 (PcdOvmfSnpSecretsSize)
%include "Ia16/ResetVectorVtf0.asm"

--
2.17.1


[RFC PATCH v5 05/28] OvmfPkg: reserve CPUID page for SEV-SNP

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Platform features and capabilities are traditionally discovered via the
CPUID instruction. Hypervisors typically trap and emulate the CPUID
instruction for a variety of reasons. There are some cases where incorrect
CPUID information can potentially lead to a security issue. The SEV-SNP
firmware provides a feature to filter the CPUID results through the PSP.
The filtered CPUID values are saved on a special page for the guest to
consume. Reserve a page in MEMFD that will contain the results of
filtered CPUID values.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/OvmfPkg.dec | 6 ++++++
OvmfPkg/OvmfPkgX64.fdf | 3 +++
2 files changed, 9 insertions(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 106a368ec975..93f759534ade 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -328,6 +328,12 @@ [PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|0|UINT32|0x47
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize|0|UINT32|0x48

+ ## The base address and size of the SEV-SNP CPUID Area that contains
+ # the PSP filtered CPUID results. If this is set in the .fdf, the
+ # platform is responsible to reserve this area from DXE phase overwrites.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|0|UINT32|0x49
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize|0|UINT32|0x50
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 902c6a4e9ea1..3e257aaf72bd 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -91,6 +91,9 @@ [FD.MEMFD]
0x00D000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize

+0x00E000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpCpuidSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

--
2.17.1


[RFC PATCH v5 04/28] OvmfPkg: reserve SNP secrets page

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

During the SNP guest launch sequence, a special secrets page needs to be
inserted by the VMM. The PSP will populate the page; it will contain the
VM Platform Communication Key (VMPCKs) used by the guest to send and
receive secure messages to the PSP.

The purpose of the secrets page in the SEV-SNP is different from the one
used in SEV guests. In SEV, the secrets page contains the guest owner's
private data after the remote attestation.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/OvmfPkg.dec | 7 +++++++
OvmfPkg/OvmfPkgX64.fdf | 3 +++
2 files changed, 10 insertions(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 6ae733f6e39f..106a368ec975 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -321,6 +321,13 @@ [PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|0x0|UINT32|0x42
gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize|0x0|UINT32|0x43

+ ## The base address and size of the SEV-SNP Secrets Area that contains
+ # the VM platform communication key used to send and recieve the
+ # messages to the PSP. If this is set in the .fdf, the platform
+ # is responsible to reserve this area from DXE phase overwrites.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|0|UINT32|0x47
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize|0|UINT32|0x48
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 5fa8c0895808..902c6a4e9ea1 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -88,6 +88,9 @@ [FD.MEMFD]
0x00C000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize

+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize

--
2.17.1


[RFC PATCH v5 03/28] OvmfPkg/ResetVector: add the macro to request guest termination

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The upcoming SEV-SNP support will need to make a few additional guest
termination requests depending on the failure type. Let's move the logic
to request the guest termination into a macro to keep the code readable.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/ResetVector/Ia32/AmdSev.asm | 87 +++++++++++++++--------------
1 file changed, 45 insertions(+), 42 deletions(-)

diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 2c478cda314b..c4c00056f9f3 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -39,6 +39,13 @@ BITS 32
%define SEV_GHCB_MSR 0xc0010130
%define SEV_STATUS_MSR 0xc0010131

+; The #VC was not for CPUID
+%define TERM_VC_NOT_CPUID 1
+
+; The unexpected response code
+%define TERM_UNEXPECTED_RESP_CODE 2
+
+
; Macro is used to issue the MSR protocol based VMGEXIT. The caller is
; responsible to populate values in the EDX:EAX registers. After the vmmcall
; returns, it verifies that the response code matches with the expected
@@ -74,6 +81,43 @@ BITS 32
jne SevEsUnexpectedRespTerminate
%endmacro

+; Macro to terminate the guest using the VMGEXIT.
+; arg 1: reason code
+%macro TerminateVmgExit 1
+ mov eax, %1
+ ;
+ ; Use VMGEXIT to request termination. At this point the reason code is
+ ; located in EAX, so shift it left 16 bits to the proper location.
+ ;
+ ; EAX[11:0] => 0x100 - request termination
+ ; EAX[15:12] => 0x1 - OVMF
+ ; EAX[23:16] => 0xXX - REASON CODE
+ ;
+ shl eax, 16
+ or eax, 0x1100
+ xor edx, edx
+ mov ecx, SEV_GHCB_MSR
+ wrmsr
+ ;
+ ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+ ; mode, so work around this by temporarily switching to 64-bit mode.
+ ;
+BITS 64
+ rep vmmcall
+BITS 32
+
+ ;
+ ; We shouldn't come back from the VMGEXIT, but if we do, just loop.
+ ;
+%%TerminateHlt:
+ hlt
+ jmp %%TerminateHlt
+%endmacro
+
+; Terminate the guest due to unexpected response code.
+SevEsUnexpectedRespTerminate:
+ TerminateVmgExit TERM_UNEXPECTED_RESP_CODE
+
; Check if Secure Encrypted Virtualization (SEV) features are enabled.
;
; Register usage is tight in this routine, so multiple calls for the
@@ -228,48 +272,7 @@ SevEsDisabled:
;

SevEsIdtNotCpuid:
- ;
- ; Use VMGEXIT to request termination.
- ; 1 - #VC was not for CPUID
- ;
- mov eax, 1
- jmp SevEsIdtTerminate
-
-SevEsUnexpectedRespTerminate:
- ;
- ; Use VMGEXIT to request termination.
- ; 2 - Unexpected Response is received
- ;
- mov eax, 2
-
-SevEsIdtTerminate:
- ;
- ; Use VMGEXIT to request termination. At this point the reason code is
- ; located in EAX, so shift it left 16 bits to the proper location.
- ;
- ; EAX[11:0] => 0x100 - request termination
- ; EAX[15:12] => 0x1 - OVMF
- ; EAX[23:16] => 0xXX - REASON CODE
- ;
- shl eax, 16
- or eax, 0x1100
- xor edx, edx
- mov ecx, SEV_GHCB_MSR
- wrmsr
- ;
- ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
- ; mode, so work around this by temporarily switching to 64-bit mode.
- ;
-BITS 64
- rep vmmcall
-BITS 32
-
- ;
- ; We shouldn't come back from the VMGEXIT, but if we do, just loop.
- ;
-SevEsIdtHlt:
- hlt
- jmp SevEsIdtHlt
+ TerminateVmgExit TERM_VC_NOT_CPUID
iret

;
--
2.17.1


[RFC PATCH v5 02/28] OvmfPkg/ResetVector: add the macro to invoke MSR protocol based VMGEXIT

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The upcoming SEV-SNP support will need to make a few additional MSR
protocol based VMGEXIT's. Add a macro that wraps the common setup and
response validation logic in one place to keep the code readable.

While at it, define SEV_STATUS_MSR that will be used to get the SEV STATUS
MSR instead of open coding it.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/ResetVector/Ia32/AmdSev.asm | 71 +++++++++++++++++++----------
1 file changed, 47 insertions(+), 24 deletions(-)

diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index b32dd3b5d656..2c478cda314b 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -36,6 +36,44 @@ BITS 32
%define CPUID_INSN_LEN 2


+%define SEV_GHCB_MSR 0xc0010130
+%define SEV_STATUS_MSR 0xc0010131
+
+; Macro is used to issue the MSR protocol based VMGEXIT. The caller is
+; responsible to populate values in the EDX:EAX registers. After the vmmcall
+; returns, it verifies that the response code matches with the expected
+; code. If it does not match then terminate the guest. The result of request
+; is returned in the EDX:EAX.
+;
+; args 1:Request code, 2: Response code
+%macro VmgExit 2
+ ;
+ ; Add request code:
+ ; GHCB_MSR[11:0] = Request code
+ or eax, %1
+
+ mov ecx, SEV_GHCB_MSR
+ wrmsr
+
+ ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+ ; mode, so work around this by temporarily switching to 64-bit mode.
+ ;
+BITS 64
+ rep vmmcall
+BITS 32
+
+ mov ecx, SEV_GHCB_MSR
+ rdmsr
+
+ ;
+ ; Verify the reponse code, if it does not match then request to terminate
+ ; GHCB_MSR[11:0] = Response code
+ mov ecx, eax
+ and ecx, 0xfff
+ cmp ecx, %2
+ jne SevEsUnexpectedRespTerminate
+%endmacro
+
; Check if Secure Encrypted Virtualization (SEV) features are enabled.
;
; Register usage is tight in this routine, so multiple calls for the
@@ -85,7 +123,7 @@ CheckSevFeatures:

; Check if SEV memory encryption is enabled
; MSR_0xC0010131 - Bit 0 (SEV enabled)
- mov ecx, 0xc0010131
+ mov ecx, SEV_STATUS_MSR
rdmsr
bt eax, 0
jnc NoSev
@@ -100,7 +138,7 @@ CheckSevFeatures:

; Check if SEV-ES is enabled
; MSR_0xC0010131 - Bit 1 (SEV-ES enabled)
- mov ecx, 0xc0010131
+ mov ecx, SEV_STATUS_MSR
rdmsr
bt eax, 1
jnc GetSevEncBit
@@ -197,10 +235,10 @@ SevEsIdtNotCpuid:
mov eax, 1
jmp SevEsIdtTerminate

-SevEsIdtNoCpuidResponse:
+SevEsUnexpectedRespTerminate:
;
; Use VMGEXIT to request termination.
- ; 2 - GHCB_CPUID_RESPONSE not received
+ ; 2 - Unexpected Response is received
;
mov eax, 2

@@ -216,7 +254,7 @@ SevEsIdtTerminate:
shl eax, 16
or eax, 0x1100
xor edx, edx
- mov ecx, 0xc0010130
+ mov ecx, SEV_GHCB_MSR
wrmsr
;
; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
@@ -276,7 +314,7 @@ SevEsIdtVmmComm:
mov [esp + VC_CPUID_REQUEST_REGISTER], eax

; Save current GHCB MSR value
- mov ecx, 0xc0010130
+ mov ecx, SEV_GHCB_MSR
rdmsr
mov [esp + VC_GHCB_MSR_EAX], eax
mov [esp + VC_GHCB_MSR_EDX], edx
@@ -293,31 +331,16 @@ NextReg:
jge VmmDone

shl eax, GHCB_CPUID_REGISTER_SHIFT
- or eax, GHCB_CPUID_REQUEST
mov edx, [esp + VC_CPUID_FUNCTION]
- mov ecx, 0xc0010130
- wrmsr

- ;
- ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
- ; mode, so work around this by temporarily switching to 64-bit mode.
- ;
-BITS 64
- rep vmmcall
-BITS 32
+ VmgExit GHCB_CPUID_REQUEST, GHCB_CPUID_RESPONSE

;
- ; Read GHCB MSR
+ ; Response GHCB MSR
; GHCB_MSR[63:32] = CPUID register value
; GHCB_MSR[31:30] = CPUID register
; GHCB_MSR[11:0] = CPUID response protocol
;
- mov ecx, 0xc0010130
- rdmsr
- mov ecx, eax
- and ecx, 0xfff
- cmp ecx, GHCB_CPUID_RESPONSE
- jne SevEsIdtNoCpuidResponse

; Save returned value
shr eax, GHCB_CPUID_REGISTER_SHIFT
@@ -335,7 +358,7 @@ VmmDone:
;
mov eax, [esp + VC_GHCB_MSR_EAX]
mov edx, [esp + VC_GHCB_MSR_EDX]
- mov ecx, 0xc0010130
+ mov ecx, SEV_GHCB_MSR
wrmsr

mov eax, [esp + VC_CPUID_RESULT_EAX]
--
2.17.1


[RFC PATCH v5 01/28] OvmfPkg/ResetVector: move SEV specific code in a separate file

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The PageTables64.asm was created to provide routines to set the CR3
register for 64-bit paging. During the SEV support, it grew to include a
lot of the SEV stuff. Before adding more SEV features, let's move all
the SEV-specific routines into a separate file.

No functionality change intended.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
.../Ia32/{PageTables64.asm => AmdSev.asm} | 140 -------
OvmfPkg/ResetVector/Ia32/PageTables64.asm | 391 ------------------
OvmfPkg/ResetVector/ResetVector.nasmb | 1 +
3 files changed, 1 insertion(+), 531 deletions(-)
copy OvmfPkg/ResetVector/Ia32/{PageTables64.asm => AmdSev.asm} (71%)

diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
similarity index 71%
copy from OvmfPkg/ResetVector/Ia32/PageTables64.asm
copy to OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 5fae8986d9da..b32dd3b5d656 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -10,33 +10,6 @@

BITS 32

-%define PAGE_PRESENT 0x01
-%define PAGE_READ_WRITE 0x02
-%define PAGE_USER_SUPERVISOR 0x04
-%define PAGE_WRITE_THROUGH 0x08
-%define PAGE_CACHE_DISABLE 0x010
-%define PAGE_ACCESSED 0x020
-%define PAGE_DIRTY 0x040
-%define PAGE_PAT 0x080
-%define PAGE_GLOBAL 0x0100
-%define PAGE_2M_MBO 0x080
-%define PAGE_2M_PAT 0x01000
-
-%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \
- PAGE_DIRTY + \
- PAGE_READ_WRITE + \
- PAGE_PRESENT)
-
-%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
- PAGE_ACCESSED + \
- PAGE_DIRTY + \
- PAGE_READ_WRITE + \
- PAGE_PRESENT)
-
-%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
- PAGE_READ_WRITE + \
- PAGE_PRESENT)
-
;
; SEV-ES #VC exception handler support
;
@@ -213,119 +186,6 @@ IsSevEsEnabled:
SevEsDisabled:
OneTimeCallRet IsSevEsEnabled

-;
-; Modified: EAX, EBX, ECX, EDX
-;
-SetCr3ForPageTables64:
-
- OneTimeCall CheckSevFeatures
- xor edx, edx
- test eax, eax
- jz SevNotActive
-
- ; If SEV is enabled, C-bit is always above 31
- sub eax, 32
- bts edx, eax
-
-SevNotActive:
-
- ;
- ; For OVMF, build some initial page tables at
- ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
- ;
- ; This range should match with PcdOvmfSecPageTablesSize which is
- ; declared in the FDF files.
- ;
- ; At the end of PEI, the pages tables will be rebuilt into a
- ; more permanent location by DxeIpl.
- ;
-
- mov ecx, 6 * 0x1000 / 4
- xor eax, eax
-clearPageTablesMemoryLoop:
- mov dword[ecx * 4 + PT_ADDR (0) - 4], eax
- loop clearPageTablesMemoryLoop
-
- ;
- ; Top level Page Directory Pointers (1 * 512GB entry)
- ;
- mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
- mov dword[PT_ADDR (4)], edx
-
- ;
- ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
- ;
- mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
- mov dword[PT_ADDR (0x1004)], edx
- mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
- mov dword[PT_ADDR (0x100C)], edx
- mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
- mov dword[PT_ADDR (0x1014)], edx
- mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
- mov dword[PT_ADDR (0x101C)], edx
-
- ;
- ; Page Table Entries (2048 * 2MB entries => 4GB)
- ;
- mov ecx, 0x800
-pageTableEntriesLoop:
- mov eax, ecx
- dec eax
- shl eax, 21
- add eax, PAGE_2M_PDE_ATTR
- mov [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
- mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
- loop pageTableEntriesLoop
-
- OneTimeCall IsSevEsEnabled
- test eax, eax
- jz SetCr3
-
- ;
- ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
- ; This requires the 2MB page for this range be broken down into 512 4KB
- ; pages. All will be marked encrypted, except for the GHCB.
- ;
- mov ecx, (GHCB_BASE >> 21)
- mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
- mov [ecx * 8 + PT_ADDR (0x2000)], eax
-
- ;
- ; Page Table Entries (512 * 4KB entries => 2MB)
- ;
- mov ecx, 512
-pageTableEntries4kLoop:
- mov eax, ecx
- dec eax
- shl eax, 12
- add eax, GHCB_BASE & 0xFFE0_0000
- add eax, PAGE_4K_PDE_ATTR
- mov [ecx * 8 + GHCB_PT_ADDR - 8], eax
- mov [(ecx * 8 + GHCB_PT_ADDR - 8) + 4], edx
- loop pageTableEntries4kLoop
-
- ;
- ; Clear the encryption bit from the GHCB entry
- ;
- mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12
- mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0
-
- mov ecx, GHCB_SIZE / 4
- xor eax, eax
-clearGhcbMemoryLoop:
- mov dword[ecx * 4 + GHCB_BASE - 4], eax
- loop clearGhcbMemoryLoop
-
-SetCr3:
- ;
- ; Set CR3 now that the paging structures are available
- ;
- mov eax, PT_ADDR (0)
- mov cr3, eax
-
- OneTimeCallRet SetCr3ForPageTables64
-
-;
; Start of #VC exception handling routines
;

diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 5fae8986d9da..eacdb69ddb9f 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -37,182 +37,6 @@ BITS 32
PAGE_READ_WRITE + \
PAGE_PRESENT)

-;
-; SEV-ES #VC exception handler support
-;
-; #VC handler local variable locations
-;
-%define VC_CPUID_RESULT_EAX 0
-%define VC_CPUID_RESULT_EBX 4
-%define VC_CPUID_RESULT_ECX 8
-%define VC_CPUID_RESULT_EDX 12
-%define VC_GHCB_MSR_EDX 16
-%define VC_GHCB_MSR_EAX 20
-%define VC_CPUID_REQUEST_REGISTER 24
-%define VC_CPUID_FUNCTION 28
-
-; #VC handler total local variable size
-;
-%define VC_VARIABLE_SIZE 32
-
-; #VC handler GHCB CPUID request/response protocol values
-;
-%define GHCB_CPUID_REQUEST 4
-%define GHCB_CPUID_RESPONSE 5
-%define GHCB_CPUID_REGISTER_SHIFT 30
-%define CPUID_INSN_LEN 2
-
-
-; Check if Secure Encrypted Virtualization (SEV) features are enabled.
-;
-; Register usage is tight in this routine, so multiple calls for the
-; same CPUID and MSR data are performed to keep things simple.
-;
-; Modified: EAX, EBX, ECX, EDX, ESP
-;
-; If SEV is enabled then EAX will be at least 32.
-; If SEV is disabled then EAX will be zero.
-;
-CheckSevFeatures:
- ; Set the first byte of the workarea to zero to communicate to the SEC
- ; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID
- ; instruction will trigger a #VC exception where the first byte of the
- ; workarea will be set to one or, if CPUID is not being intercepted,
- ; the MSR check below will set the first byte of the workarea to one.
- mov byte[SEV_ES_WORK_AREA], 0
-
- ;
- ; Set up exception handlers to check for SEV-ES
- ; Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
- ; stack usage)
- ; Establish exception handlers
- ;
- mov esp, SEV_ES_VC_TOP_OF_STACK
- mov eax, ADDR_OF(Idtr)
- lidt [cs:eax]
-
- ; Check if we have a valid (0x8000_001F) CPUID leaf
- ; CPUID raises a #VC exception if running as an SEV-ES guest
- mov eax, 0x80000000
- cpuid
-
- ; This check should fail on Intel or Non SEV AMD CPUs. In future if
- ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
- ; same bit definition.
- cmp eax, 0x8000001f
- jl NoSev
-
- ; Check for SEV memory encryption feature:
- ; CPUID Fn8000_001F[EAX] - Bit 1
- ; CPUID raises a #VC exception if running as an SEV-ES guest
- mov eax, 0x8000001f
- cpuid
- bt eax, 1
- jnc NoSev
-
- ; Check if SEV memory encryption is enabled
- ; MSR_0xC0010131 - Bit 0 (SEV enabled)
- mov ecx, 0xc0010131
- rdmsr
- bt eax, 0
- jnc NoSev
-
- ; Check for SEV-ES memory encryption feature:
- ; CPUID Fn8000_001F[EAX] - Bit 3
- ; CPUID raises a #VC exception if running as an SEV-ES guest
- mov eax, 0x8000001f
- cpuid
- bt eax, 3
- jnc GetSevEncBit
-
- ; Check if SEV-ES is enabled
- ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled)
- mov ecx, 0xc0010131
- rdmsr
- bt eax, 1
- jnc GetSevEncBit
-
- ; Set the first byte of the workarea to one to communicate to the SEC
- ; phase that SEV-ES is enabled.
- mov byte[SEV_ES_WORK_AREA], 1
-
-GetSevEncBit:
- ; Get pte bit position to enable memory encryption
- ; CPUID Fn8000_001F[EBX] - Bits 5:0
- ;
- and ebx, 0x3f
- mov eax, ebx
-
- ; The encryption bit position is always above 31
- sub ebx, 32
- jns SevSaveMask
-
- ; Encryption bit was reported as 31 or below, enter a HLT loop
-SevEncBitLowHlt:
- cli
- hlt
- jmp SevEncBitLowHlt
-
-SevSaveMask:
- xor edx, edx
- bts edx, ebx
-
- mov dword[SEV_ES_WORK_AREA_ENC_MASK], 0
- mov dword[SEV_ES_WORK_AREA_ENC_MASK + 4], edx
- jmp SevExit
-
-NoSev:
- ;
- ; Perform an SEV-ES sanity check by seeing if a #VC exception occurred.
- ;
- cmp byte[SEV_ES_WORK_AREA], 0
- jz NoSevPass
-
- ;
- ; A #VC was received, yet CPUID indicates no SEV-ES support, something
- ; isn't right.
- ;
-NoSevEsVcHlt:
- cli
- hlt
- jmp NoSevEsVcHlt
-
-NoSevPass:
- xor eax, eax
-
-SevExit:
- ;
- ; Clear exception handlers and stack
- ;
- push eax
- mov eax, ADDR_OF(IdtrClear)
- lidt [cs:eax]
- pop eax
- mov esp, 0
-
- OneTimeCallRet CheckSevFeatures
-
-; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature
-; is enabled.
-;
-; Modified: EAX
-;
-; If SEV-ES is enabled then EAX will be non-zero.
-; If SEV-ES is disabled then EAX will be zero.
-;
-IsSevEsEnabled:
- xor eax, eax
-
- ; During CheckSevFeatures, the SEV_ES_WORK_AREA was set to 1 if
- ; SEV-ES is enabled.
- cmp byte[SEV_ES_WORK_AREA], 1
- jne SevEsDisabled
-
- mov eax, 1
-
-SevEsDisabled:
- OneTimeCallRet IsSevEsEnabled
-
;
; Modified: EAX, EBX, ECX, EDX
;
@@ -324,218 +148,3 @@ SetCr3:
mov cr3, eax

OneTimeCallRet SetCr3ForPageTables64
-
-;
-; Start of #VC exception handling routines
-;
-
-SevEsIdtNotCpuid:
- ;
- ; Use VMGEXIT to request termination.
- ; 1 - #VC was not for CPUID
- ;
- mov eax, 1
- jmp SevEsIdtTerminate
-
-SevEsIdtNoCpuidResponse:
- ;
- ; Use VMGEXIT to request termination.
- ; 2 - GHCB_CPUID_RESPONSE not received
- ;
- mov eax, 2
-
-SevEsIdtTerminate:
- ;
- ; Use VMGEXIT to request termination. At this point the reason code is
- ; located in EAX, so shift it left 16 bits to the proper location.
- ;
- ; EAX[11:0] => 0x100 - request termination
- ; EAX[15:12] => 0x1 - OVMF
- ; EAX[23:16] => 0xXX - REASON CODE
- ;
- shl eax, 16
- or eax, 0x1100
- xor edx, edx
- mov ecx, 0xc0010130
- wrmsr
- ;
- ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
- ; mode, so work around this by temporarily switching to 64-bit mode.
- ;
-BITS 64
- rep vmmcall
-BITS 32
-
- ;
- ; We shouldn't come back from the VMGEXIT, but if we do, just loop.
- ;
-SevEsIdtHlt:
- hlt
- jmp SevEsIdtHlt
- iret
-
- ;
- ; Total stack usage for the #VC handler is 44 bytes:
- ; - 12 bytes for the exception IRET (after popping error code)
- ; - 32 bytes for the local variables.
- ;
-SevEsIdtVmmComm:
- ;
- ; If we're here, then we are an SEV-ES guest and this
- ; was triggered by a CPUID instruction
- ;
- ; Set the first byte of the workarea to one to communicate that
- ; a #VC was taken.
- mov byte[SEV_ES_WORK_AREA], 1
-
- pop ecx ; Error code
- cmp ecx, 0x72 ; Be sure it was CPUID
- jne SevEsIdtNotCpuid
-
- ; Set up local variable room on the stack
- ; CPUID function : + 28
- ; CPUID request register : + 24
- ; GHCB MSR (EAX) : + 20
- ; GHCB MSR (EDX) : + 16
- ; CPUID result (EDX) : + 12
- ; CPUID result (ECX) : + 8
- ; CPUID result (EBX) : + 4
- ; CPUID result (EAX) : + 0
- sub esp, VC_VARIABLE_SIZE
-
- ; Save the CPUID function being requested
- mov [esp + VC_CPUID_FUNCTION], eax
-
- ; The GHCB CPUID protocol uses the following mapping to request
- ; a specific register:
- ; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX
- ;
- ; Set EAX as the first register to request. This will also be used as a
- ; loop variable to request all register values (EAX to EDX).
- xor eax, eax
- mov [esp + VC_CPUID_REQUEST_REGISTER], eax
-
- ; Save current GHCB MSR value
- mov ecx, 0xc0010130
- rdmsr
- mov [esp + VC_GHCB_MSR_EAX], eax
- mov [esp + VC_GHCB_MSR_EDX], edx
-
-NextReg:
- ;
- ; Setup GHCB MSR
- ; GHCB_MSR[63:32] = CPUID function
- ; GHCB_MSR[31:30] = CPUID register
- ; GHCB_MSR[11:0] = CPUID request protocol
- ;
- mov eax, [esp + VC_CPUID_REQUEST_REGISTER]
- cmp eax, 4
- jge VmmDone
-
- shl eax, GHCB_CPUID_REGISTER_SHIFT
- or eax, GHCB_CPUID_REQUEST
- mov edx, [esp + VC_CPUID_FUNCTION]
- mov ecx, 0xc0010130
- wrmsr
-
- ;
- ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
- ; mode, so work around this by temporarily switching to 64-bit mode.
- ;
-BITS 64
- rep vmmcall
-BITS 32
-
- ;
- ; Read GHCB MSR
- ; GHCB_MSR[63:32] = CPUID register value
- ; GHCB_MSR[31:30] = CPUID register
- ; GHCB_MSR[11:0] = CPUID response protocol
- ;
- mov ecx, 0xc0010130
- rdmsr
- mov ecx, eax
- and ecx, 0xfff
- cmp ecx, GHCB_CPUID_RESPONSE
- jne SevEsIdtNoCpuidResponse
-
- ; Save returned value
- shr eax, GHCB_CPUID_REGISTER_SHIFT
- mov [esp + eax * 4], edx
-
- ; Next register
- inc word [esp + VC_CPUID_REQUEST_REGISTER]
-
- jmp NextReg
-
-VmmDone:
- ;
- ; At this point we have all CPUID register values. Restore the GHCB MSR,
- ; set the return register values and return.
- ;
- mov eax, [esp + VC_GHCB_MSR_EAX]
- mov edx, [esp + VC_GHCB_MSR_EDX]
- mov ecx, 0xc0010130
- wrmsr
-
- mov eax, [esp + VC_CPUID_RESULT_EAX]
- mov ebx, [esp + VC_CPUID_RESULT_EBX]
- mov ecx, [esp + VC_CPUID_RESULT_ECX]
- mov edx, [esp + VC_CPUID_RESULT_EDX]
-
- add esp, VC_VARIABLE_SIZE
-
- ; Update the EIP value to skip over the now handled CPUID instruction
- ; (the CPUID instruction has a length of 2)
- add word [esp], CPUID_INSN_LEN
- iret
-
-ALIGN 2
-
-Idtr:
- dw IDT_END - IDT_BASE - 1 ; Limit
- dd ADDR_OF(IDT_BASE) ; Base
-
-IdtrClear:
- dw 0 ; Limit
- dd 0 ; Base
-
-ALIGN 16
-
-;
-; The Interrupt Descriptor Table (IDT)
-; This will be used to determine if SEV-ES is enabled. Upon execution
-; of the CPUID instruction, a VMM Communication Exception will occur.
-; This will tell us if SEV-ES is enabled. We can use the current value
-; of the GHCB MSR to determine the SEV attributes.
-;
-IDT_BASE:
-;
-; Vectors 0 - 28 (No handlers)
-;
-%rep 29
- dw 0 ; Offset low bits 15..0
- dw 0x10 ; Selector
- db 0 ; Reserved
- db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
- dw 0 ; Offset high bits 31..16
-%endrep
-;
-; Vector 29 (VMM Communication Exception)
-;
- dw (ADDR_OF(SevEsIdtVmmComm) & 0xffff) ; Offset low bits 15..0
- dw 0x10 ; Selector
- db 0 ; Reserved
- db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
- dw (ADDR_OF(SevEsIdtVmmComm) >> 16) ; Offset high bits 31..16
-;
-; Vectors 30 - 31 (No handlers)
-;
-%rep 2
- dw 0 ; Offset low bits 15..0
- dw 0x10 ; Selector
- db 0 ; Reserved
- db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
- dw 0 ; Offset high bits 31..16
-%endrep
-IDT_END:
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 5fbacaed5f9d..8a3269cfc212 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -77,6 +77,7 @@
%define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
%define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
%include "Ia32/Flat32ToFlat64.asm"
+%include "Ia32/AmdSev.asm"
%include "Ia32/PageTables64.asm"
%endif

--
2.17.1


[RFC PATCH v5 00/28] Add AMD Secure Nested Paging (SEV-SNP) support

Brijesh Singh
 

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

SEV-SNP builds upon existing SEV and SEV-ES functionality while adding
new hardware-based memory protections. SEV-SNP adds strong memory integrity
protection to help prevent malicious hypervisor-based attacks like data
replay, memory re-mapping and more in order to create an isolated memory
encryption environment.

This series provides the basic building blocks to support booting the SEV-SNP
VMs, it does not cover all the security enhancement introduced by the SEV-SNP
such as interrupt protection.

Many of the integrity guarantees of SEV-SNP are enforced through a new
structure called the Reverse Map Table (RMP). Adding a new page to SEV-SNP
VM requires a 2-step process. First, the hypervisor assigns a page to the
guest using the new RMPUPDATE instruction. This transitions the page to
guest-invalid. Second, the guest validates the page using the new PVALIDATE
instruction. The SEV-SNP VMs can use the new "Page State Change Request NAE"
defined in the GHCB specification to ask hypervisor to add or remove page
from the RMP table.

Each page assigned to the SEV-SNP VM can either be validated or unvalidated,
as indicated by the Validated flag in the page's RMP entry. There are two
approaches that can be taken for the page validation: Pre-validation and
Lazy Validation.

Under pre-validation, the pages are validated prior to first use. And under
lazy validation, pages are validated when first accessed. An access to a
unvalidated page results in a #VC exception, at which time the exception
handler may validate the page. Lazy validation requires careful tracking of
the validated pages to avoid validating the same GPA more than once. The
recently introduced "Unaccepted" memory type can be used to communicate the
unvalidated memory ranges to the Guest OS.

At this time we only support the pre-validation. OVMF detects all the available
system RAM in the PEI phase. When SEV-SNP is enabled, the memory is validated
before it is made available to the EDK2 core.

This series does not implements the following SEV-SNP features yet:

* CPUID filtering
* Lazy validation
* Interrupt security

Additional resources
---------------------
SEV-SNP whitepaper
https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf

APM 2: https://www.amd.com/system/files/TechDocs/24593.pdf (section 15.36)

The complete source is available at
https://github.com/AMDESE/ovmf/tree/sev-snp-rfc-5

GHCB spec:
https://developer.amd.com/wp-content/resources/56421.pdf

SEV-SNP firmware specification:
https://www.amd.com/system/files/TechDocs/56860.pdf

Change since v4:
* Use the correct MSR for the SEV_STATUS
* Add VMPL-0 check

Change since v3:
* ResetVector: move all SEV specific code in AmdSev.asm and add macros to keep
the code readable.
* Drop extending the EsWorkArea to contain SNP specific state.
* Drop the GhcbGpa library and call the VmgExit directly to register GHCB GPA.
* Install the CC blob config table from AmdSevDxe instead of extending the
AmdSev/SecretsDxe for it.
* Add the separate PCDs for the SNP Secrets.

Changes since v2:
* Add support for the AP creation.
* Use the module-scoping override to make AmdSevDxe use the IO port for PCI reads.
* Use the reserved memory type for CPUID and Secrets page.
*
Changes since v1:
* Drop the interval tree support to detect the pre-validated overlap region.
* Use an array to keep track of pre-validated regions.
* Add support to query the Hypervisor feature and verify that SNP feature is supported.
* Introduce MemEncryptSevClearMmioPageEncMask() to clear the C-bit from MMIO ranges.
* Pull the SevSecretDxe and SevSecretPei into OVMF package build.
* Extend the SevSecretDxe to expose confidential computing blob location through
EFI configuration table.

Brijesh Singh (27):
OvmfPkg/ResetVector: move SEV specific code in a separate file
OvmfPkg/ResetVector: add the macro to invoke MSR protocol based
VMGEXIT
OvmfPkg/ResetVector: add the macro to request guest termination
OvmfPkg: reserve SNP secrets page
OvmfPkg: reserve CPUID page for SEV-SNP
OvmfPkg/ResetVector: introduce SEV-SNP boot block GUID
OvmfPkg/ResetVector: pre-validate the data pages used in SEC phase
OvmfPkg/ResetVector: invalidate the GHCB page
OvmfPkg/ResetVector: check the vmpl level
UefiCpuPkg: Define the SEV-SNP specific dynamic PCDs
OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled()
OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest
OvmfPkg/PlatformPei: register GHCB gpa for the SEV-SNP guest
OvmfPkg/AmdSevDxe: do not use extended PCI config space
OvmfPkg/MemEncryptSevLib: add support to validate system RAM
OvmfPkg/BaseMemEncryptSevLib: skip the pre-validated system RAM
OvmfPkg/MemEncryptSevLib: add support to validate > 4GB memory in PEI
phase
OvmfPkg/SecMain: pre-validate the memory used for decompressing Fv
OvmfPkg/PlatformPei: validate the system RAM when SNP is active
OvmfPkg/PlatformPei: set the SEV-SNP enabled PCD
OvmfPkg/PlatformPei: set the Hypervisor Features PCD
MdePkg/GHCB: increase the GHCB protocol max version
UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is
enabled
OvmfPkg/MemEncryptSevLib: change the page state in the RMP table
OvmfPkg/MemEncryptSevLib: skip page state change for Mmio address
OvmfPkg/PlatformPei: mark cpuid and secrets memory reserved in EFI map
OvmfPkg/AmdSev: expose the SNP reserved pages through configuration
table

Tom Lendacky (1):
UefiCpuPkg/MpInitLib: Use SEV-SNP AP Creation NAE event to launch APs

OvmfPkg/OvmfPkg.dec | 24 +
UefiCpuPkg/UefiCpuPkg.dec | 11 +
OvmfPkg/AmdSev/AmdSevX64.dsc | 5 +-
OvmfPkg/Bhyve/BhyveX64.dsc | 5 +-
OvmfPkg/OvmfPkgIa32.dsc | 1 +
OvmfPkg/OvmfPkgIa32X64.dsc | 6 +-
OvmfPkg/OvmfPkgX64.dsc | 5 +-
OvmfPkg/OvmfXen.dsc | 5 +-
OvmfPkg/OvmfPkgX64.fdf | 14 +-
OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 7 +
.../DxeMemEncryptSevLib.inf | 3 +
.../PeiMemEncryptSevLib.inf | 7 +
.../SecMemEncryptSevLib.inf | 3 +
OvmfPkg/PlatformPei/PlatformPei.inf | 8 +
OvmfPkg/ResetVector/ResetVector.inf | 6 +
OvmfPkg/Sec/SecMain.inf | 3 +
UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 4 +
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 4 +
MdePkg/Include/Register/Amd/Ghcb.h | 2 +-
.../Guid/ConfidentialComputingSecret.h | 18 +
OvmfPkg/Include/Library/MemEncryptSevLib.h | 26 +
.../X64/SnpPageStateChange.h | 31 ++
.../BaseMemEncryptSevLib/X64/VirtualMemory.h | 19 +
UefiCpuPkg/Library/MpInitLib/MpLib.h | 19 +
OvmfPkg/AmdSevDxe/AmdSevDxe.c | 23 +
.../DxeMemEncryptSevLibInternal.c | 27 +
.../Ia32/MemEncryptSevLib.c | 17 +
.../PeiMemEncryptSevLibInternal.c | 27 +
.../SecMemEncryptSevLibInternal.c | 19 +
.../X64/DxeSnpSystemRamValidate.c | 40 ++
.../X64/PeiDxeVirtualMemory.c | 167 +++++-
.../X64/PeiSnpSystemRamValidate.c | 126 +++++
.../X64/SecSnpSystemRamValidate.c | 36 ++
.../X64/SnpPageStateChangeInternal.c | 295 ++++++++++
OvmfPkg/PlatformPei/AmdSev.c | 192 +++++++
OvmfPkg/PlatformPei/MemDetect.c | 21 +
OvmfPkg/Sec/SecMain.c | 111 ++++
UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 11 +-
.../MpInitLib/Ia32/SevSnpRmpAdjustInternal.c | 31 ++
UefiCpuPkg/Library/MpInitLib/MpLib.c | 275 +++++++++-
.../MpInitLib/X64/SevSnpRmpAdjustInternal.c | 44 ++
OvmfPkg/FvmainCompactScratchEnd.fdf.inc | 5 +
OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 27 +
.../Ia32/{PageTables64.asm => AmdSev.asm} | 502 +++++++++++-------
OvmfPkg/ResetVector/Ia32/PageTables64.asm | 404 +-------------
OvmfPkg/ResetVector/ResetVector.nasmb | 7 +
UefiCpuPkg/Library/MpInitLib/MpEqu.inc | 1 +
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 51 ++
48 files changed, 2065 insertions(+), 630 deletions(-)
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChange.h
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/DxeSnpSystemRamValidate.c
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiSnpSystemRamValidate.c
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c
create mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/SevSnpRmpAdjustInternal.c
create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/SevSnpRmpAdjustInternal.c
copy OvmfPkg/ResetVector/Ia32/{PageTables64.asm => AmdSev.asm} (57%)

--
2.17.1


[edk2-platforms PATCH v4 12/12] Platform/RaspberryPi: Enable default Secure Boot variables initialization

Grzegorz Bernacki
 

This commit allows to initialize Secure Boot default key
and databases from data embedded in firmware binary.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
Reviewed-by: Sunny Wang <sunny.wang@arm.com>
Reviewed-by: Pete Batard <pete@akeo.ie>
Tested-by: Pete Batard <pete@akeo.ie> on Raspberry Pi 4
---
Platform/RaspberryPi/RPi4/RPi4.dsc | 3 +++
Platform/RaspberryPi/RPi4/RPi4.fdf | 2 ++
2 files changed, 5 insertions(+)

diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index d38fee8fb8..54bb282ff2 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -218,6 +218,7 @@
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf

[LibraryClasses.common.UEFI_DRIVER]
@@ -621,6 +622,8 @@
NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
}
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+ SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf
+ SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf
!else
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
!endif
diff --git a/Platform/RaspberryPi/RPi4/RPi4.fdf b/Platform/RaspberryPi/RPi4/RPi4.fdf
index 1e13909a57..8508065a77 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.fdf
+++ b/Platform/RaspberryPi/RPi4/RPi4.fdf
@@ -189,7 +189,9 @@ READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
!if $(SECURE_BOOT_ENABLE) == TRUE
+!include ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc
INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+ INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf
!endif
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
--
2.25.1


[edk2-platforms PATCH v4 11/12] RISC-V Platforms: add SecureBootVariableLib class resolution

Grzegorz Bernacki
 

The edk2 patch
SecurityPkg: Create library for setting Secure Boot variables.

removes generic functions from SecureBootConfigDxe and places
them into SecureBootVariableLib. This patch adds SecureBootVariableLib
mapping for each RICS-V platform which uses SecureBootConfigDxe.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
Platform/SiFive/U5SeriesPkg/FreedomU500VC707Board/U500.dsc | 1 +
Platform/SiFive/U5SeriesPkg/FreedomU540HiFiveUnleashedBoard/U540.dsc | 1 +
2 files changed, 2 insertions(+)

diff --git a/Platform/SiFive/U5SeriesPkg/FreedomU500VC707Board/U500.dsc b/Platform/SiFive/U5SeriesPkg/FreedomU500VC707Board/U500.dsc
index b91823ceeb..fc5ba2a07f 100644
--- a/Platform/SiFive/U5SeriesPkg/FreedomU500VC707Board/U500.dsc
+++ b/Platform/SiFive/U5SeriesPkg/FreedomU500VC707Board/U500.dsc
@@ -122,6 +122,7 @@
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
diff --git a/Platform/SiFive/U5SeriesPkg/FreedomU540HiFiveUnleashedBoard/U540.dsc b/Platform/SiFive/U5SeriesPkg/FreedomU540HiFiveUnleashedBoard/U540.dsc
index 0eafe29880..71add8ff9a 100644
--- a/Platform/SiFive/U5SeriesPkg/FreedomU540HiFiveUnleashedBoard/U540.dsc
+++ b/Platform/SiFive/U5SeriesPkg/FreedomU540HiFiveUnleashedBoard/U540.dsc
@@ -122,6 +122,7 @@
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
--
2.25.1


[edk2-platforms PATCH v4 10/12] ARM Silicon and Platforms: add SecureBootVariableLib class resolution

Grzegorz Bernacki
 

The edk2 patch
SecurityPkg: Create library for setting Secure Boot variables.

removes generic functions from SecureBootConfigDxe and places
them into SecureBootVariableLib. This patch adds SecureBootVariableLib
mapping for each ARM platform which uses SecureBootConfigDxe.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc | 1 +
Platform/Qemu/SbsaQemu/SbsaQemu.dsc | 1 +
Platform/RaspberryPi/RPi3/RPi3.dsc | 1 +
Platform/RaspberryPi/RPi4/RPi4.dsc | 1 +
Platform/Socionext/DeveloperBox/DeveloperBox.dsc | 4 ++++
5 files changed, 8 insertions(+)

diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
index fee7cfcc2d..60fdb244ba 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
@@ -129,6 +129,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf

# re-use the UserPhysicalPresent() dummy implementation from the ovmf tree
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
diff --git a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
index 11ce361cdb..b1c4030ec9 100644
--- a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
+++ b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
@@ -156,6 +156,7 @@ DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
#
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf

# re-use the UserPhysicalPresent() dummy implementation from the ovmf tree
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
diff --git a/Platform/RaspberryPi/RPi3/RPi3.dsc b/Platform/RaspberryPi/RPi3/RPi3.dsc
index 53825bcf62..73f7f2f8c3 100644
--- a/Platform/RaspberryPi/RPi3/RPi3.dsc
+++ b/Platform/RaspberryPi/RPi3/RPi3.dsc
@@ -167,6 +167,7 @@

# re-use the UserPhysicalPresent() dummy implementation from the ovmf tree
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index fd73c4d14b..d38fee8fb8 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -164,6 +164,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf

# re-use the UserPhysicalPresent() dummy implementation from the ovmf tree
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
diff --git a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
index 88454c1f90..41b7c3bced 100644
--- a/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
+++ b/Platform/Socionext/DeveloperBox/DeveloperBox.dsc
@@ -52,6 +52,10 @@

MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf

+!if $(SECURE_BOOT_ENABLE) == TRUE
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
+!endif
+
[LibraryClasses.common.SEC]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
--
2.25.1


[edk2-platforms PATCH v4 09/12] Intel Platforms: add SecureBootVariableLib class resolution

Grzegorz Bernacki
 

The edk2 patch
SecurityPkg: Create library for setting Secure Boot variables.

removes generic functions from SecureBootConfigDxe and places
them into SecureBootVariableLib. This patch adds SecureBootVariableLib
mapping for each Intel platform which uses SecureBootConfigDxe.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc | 1 +
Platform/Intel/QuarkPlatformPkg/Quark.dsc | 1 +
Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc | 1 +
Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgX64.dsc | 3 ++-
4 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
index b154f9615d..5157c87a9a 100644
--- a/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
+++ b/Platform/Intel/MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc
@@ -139,6 +139,7 @@

!if gMinPlatformPkgTokenSpaceGuid.PcdUefiSecureBootEnable == TRUE
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!endif

SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
diff --git a/Platform/Intel/QuarkPlatformPkg/Quark.dsc b/Platform/Intel/QuarkPlatformPkg/Quark.dsc
index cc1eba4df4..35f99429f7 100644
--- a/Platform/Intel/QuarkPlatformPkg/Quark.dsc
+++ b/Platform/Intel/QuarkPlatformPkg/Quark.dsc
@@ -175,6 +175,7 @@
!if $(SECURE_BOOT_ENABLE)
PlatformSecureLib|QuarkPlatformPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc b/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
index d15da40819..5a0d3e31e1 100644
--- a/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
+++ b/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgIA32.dsc
@@ -227,6 +227,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgX64.dsc b/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
index 4a5548b80e..36a5ae333c 100644
--- a/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
+++ b/Platform/Intel/Vlv2TbltDevicePkg/PlatformPkgX64.dsc
@@ -1,4 +1,4 @@
-#/** @file
+e
# Platform description.
#
# Copyright (c) 2012 - 2021, Intel Corporation. All rights reserved.<BR>
@@ -229,6 +229,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
--
2.25.1


[PATCH v4 8/8] SecurityPkg: Add option to reset secure boot keys.

Grzegorz Bernacki
 

This commit add option which allows reset content of Secure Boot
keys and databases to default variables.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
Reviewed-by: Sunny Wang <sunny.wang@arm.com>
Reviewed-by: Pete Batard <pete@akeo.ie>
Tested-by: Pete Batard <pete@akeo.ie> on Raspberry Pi 4
---
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf | 1 +
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h | 2 +
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr | 6 +
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c | 154 ++++++++++++++++++++
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni | 4 +
5 files changed, 167 insertions(+)

diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
index 30d9cd8025..bd8d256dde 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -109,6 +109,7 @@
[Protocols]
gEfiHiiConfigAccessProtocolGuid ## PRODUCES
gEfiDevicePathProtocolGuid ## PRODUCES
+ gEfiHiiPopupProtocolGuid

[Depex]
gEfiHiiConfigRoutingProtocolGuid AND
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
index 6e54a4b0f2..4ecc25efc3 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
@@ -54,6 +54,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

#define KEY_VALUE_FROM_DBX_TO_LIST_FORM 0x100f

+#define KEY_SECURE_BOOT_RESET_TO_DEFAULT 0x1010
+
#define KEY_SECURE_BOOT_OPTION 0x1100
#define KEY_SECURE_BOOT_PK_OPTION 0x1101
#define KEY_SECURE_BOOT_KEK_OPTION 0x1102
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
index fa7e11848c..e4560c592c 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
@@ -69,6 +69,12 @@ formset
endif;
endif;

+ text
+ help = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS_HELP),
+ text = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS),
+ flags = INTERACTIVE,
+ key = KEY_SECURE_BOOT_RESET_TO_DEFAULT;
+
endform;

//
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
index 67e5e594ed..47f281873b 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
@@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "SecureBootConfigImpl.h"
+#include <Protocol/HiiPopup.h>
#include <Library/BaseCryptLib.h>
#include <Library/SecureBootVariableLib.h>

@@ -4154,6 +4155,132 @@ ON_EXIT:
return Status;
}

+/**
+ This function reinitializes Secure Boot variables with default values.
+
+ @retval EFI_SUCCESS Success to update the signature list page
+ @retval others Fail to delete or enroll signature data.
+**/
+
+STATIC EFI_STATUS
+EFIAPI
+KeyEnrollReset (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 SetupMode;
+
+ Status = EFI_SUCCESS;
+
+ Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ // Clear all the keys and databases
+ Status = DeleteDb ();
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((DEBUG_ERROR, "Fail to clear DB: %r\n", Status));
+ return Status;
+ }
+
+ Status = DeleteDbx ();
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((DEBUG_ERROR, "Fail to clear DBX: %r\n", Status));
+ return Status;
+ }
+
+ Status = DeleteDbt ();
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((DEBUG_ERROR, "Fail to clear DBT: %r\n", Status));
+ return Status;
+ }
+
+ Status = DeleteKEK ();
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((DEBUG_ERROR, "Fail to clear KEK: %r\n", Status));
+ return Status;
+ }
+
+ Status = DeletePlatformKey ();
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((DEBUG_ERROR, "Fail to clear PK: %r\n", Status));
+ return Status;
+ }
+
+ // After PK clear, Setup Mode shall be enabled
+ Status = GetSetupMode (&SetupMode);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot get SetupMode variable: %r\n",
+ Status));
+ return Status;
+ }
+
+ if (SetupMode == USER_MODE) {
+ DEBUG((DEBUG_INFO, "Skipped - USER_MODE\n"));
+ return EFI_SUCCESS;
+ }
+
+ Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n",
+ Status));
+ return EFI_SUCCESS;
+ }
+
+ // Enroll all the keys from default variables
+ Status = EnrollDbFromDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot enroll db: %r\n", Status));
+ goto error;
+ }
+
+ Status = EnrollDbxFromDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot enroll dbx: %r\n", Status));
+ }
+
+ Status = EnrollDbtFromDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot enroll dbt: %r\n", Status));
+ }
+
+ Status = EnrollKEKFromDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot enroll KEK: %r\n", Status));
+ goto cleardbs;
+ }
+
+ Status = EnrollPKFromDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot enroll PK: %r\n", Status));
+ goto clearKEK;
+ }
+
+ Status = SetSecureBootMode (STANDARD_SECURE_BOOT_MODE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
+ "Please do it manually, otherwise system can be easily compromised\n"));
+ }
+
+ return Status;
+
+clearKEK:
+ DeleteKEK ();
+
+cleardbs:
+ DeleteDbt ();
+ DeleteDbx ();
+ DeleteDb ();
+
+error:
+ if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Cannot set mode to Secure: %r\n", Status));
+ }
+ return Status;
+}
+
/**
This function is called to provide results data to the driver.

@@ -4205,6 +4332,8 @@ SecureBootCallback (
SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
BOOLEAN GetBrowserDataResult;
ENROLL_KEY_ERROR EnrollKeyErrorCode;
+ EFI_HII_POPUP_PROTOCOL *HiiPopup;
+ EFI_HII_POPUP_SELECTION UserSelection;

Status = EFI_SUCCESS;
SecureBootEnable = NULL;
@@ -4755,6 +4884,31 @@ SecureBootCallback (
FreePool (SetupMode);
}
break;
+ case KEY_SECURE_BOOT_RESET_TO_DEFAULT:
+ {
+ Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **) &HiiPopup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = HiiPopup->CreatePopup (
+ HiiPopup,
+ EfiHiiPopupStyleInfo,
+ EfiHiiPopupTypeYesNo,
+ Private->HiiHandle,
+ STRING_TOKEN (STR_RESET_TO_DEFAULTS_POPUP),
+ &UserSelection
+ );
+ if (UserSelection == EfiHiiPopupSelectionYes) {
+ Status = KeyEnrollReset ();
+ }
+ //
+ // Update secure boot strings after key reset
+ //
+ if (Status == EFI_SUCCESS) {
+ Status = UpdateSecureBootString (Private);
+ SecureBootExtractConfigFromVariable (Private, IfrNvData);
+ }
+ }
default:
break;
}
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
index ac783453cc..0d01701de7 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
@@ -21,6 +21,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#string STR_SECURE_BOOT_PROMPT #language en-US "Attempt Secure Boot"
#string STR_SECURE_BOOT_HELP #language en-US "Enable/Disable the Secure Boot feature after platform reset"

+#string STR_SECURE_RESET_TO_DEFAULTS_HELP #language en-US "Enroll keys with data from default variables"
+#string STR_SECURE_RESET_TO_DEFAULTS #language en-US "Reset Secure Boot Keys"
+#string STR_RESET_TO_DEFAULTS_POPUP #language en-US "Secure Boot Keys & databases will be initialized from defaults.\n Are you sure?"
+
#string STR_SECURE_BOOT_ENROLL_SIGNATURE #language en-US "Enroll Signature"
#string STR_SECURE_BOOT_DELETE_SIGNATURE #language en-US "Delete Signature"
#string STR_SECURE_BOOT_DELETE_LIST_FORM #language en-US "Delete Signature List Form"
--
2.25.1


[PATCH v4 7/8] SecurityPkg: Add new modules to Security package.

Grzegorz Bernacki
 

This commits adds modules related to initialization and
usage of default Secure Boot key variables to SecurityPkg.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
Reviewed-by: Sunny Wang <sunny.wang@arm.com>
Reviewed-by: Pete Batard <pete@akeo.ie>
Tested-by: Pete Batard <pete@akeo.ie> on Raspberry Pi 4
---
SecurityPkg/SecurityPkg.dec | 14 ++++++++++++++
SecurityPkg/SecurityPkg.dsc | 3 +++
2 files changed, 17 insertions(+)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 4001650fa2..e6aab4dce7 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -190,6 +190,20 @@
## GUID used to enforce loading order between Tcg2Acpi and Tcg2Smm
gTcg2MmSwSmiRegisteredGuid = { 0x9d4548b9, 0xa48d, 0x4db4, { 0x9a, 0x68, 0x32, 0xc5, 0x13, 0x9e, 0x20, 0x18 } }

+ ## GUID used to specify section with default PK content
+ gDefaultPKFileGuid = { 0x85254ea7, 0x4759, 0x4fc4, { 0x82, 0xd4, 0x5e, 0xed, 0x5f, 0xb0, 0xa4, 0xa0 } }
+
+ ## GUID used to specify section with default KEK content
+ gDefaultKEKFileGuid = { 0x6f64916e, 0x9f7a, 0x4c35, { 0xb9, 0x52, 0xcd, 0x04, 0x1e, 0xfb, 0x05, 0xa3 } }
+
+ ## GUID used to specify section with default db content
+ gDefaultdbFileGuid = { 0xc491d352, 0x7623, 0x4843, { 0xac, 0xcc, 0x27, 0x91, 0xa7, 0x57, 0x44, 0x21 } }
+
+ ## GUID used to specify section with default dbx content
+ gDefaultdbxFileGuid = { 0x5740766a, 0x718e, 0x4dc0, { 0x99, 0x35, 0xc3, 0x6f, 0x7d, 0x3f, 0x88, 0x4f } }
+
+ ## GUID used to specify section with default dbt content
+ gDefaultdbtFileGuid = { 0x36c513ee, 0xa338, 0x4976, { 0xa0, 0xfb, 0x6d, 0xdb, 0xa3, 0xda, 0xfe, 0x87 } }

[Ppis]
## The PPI GUID for that TPM physical presence should be locked.
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 854f250625..f2f90f49de 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -259,6 +259,9 @@

[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
+ SecurityPkg/EnrollFromDefaultKeys/EnrollFromDefaultKeys.inf
+ SecurityPkg/VariableAuthenticated/SecureBootDefaultKeys/SecureBootDefaultKeys.inf

[Components.IA32, Components.X64, Components.AARCH64]
#
--
2.25.1


[PATCH v4 6/8] SecurityPkg: Add EnrollFromDefaultKeys application.

Grzegorz Bernacki
 

This application allows user to force key enrollment from
Secure Boot default variables.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf | 47 +++++++++
SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.c | 109 ++++++++++++++++++++
2 files changed, 156 insertions(+)
create mode 100644 SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf
create mode 100644 SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.c

diff --git a/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf b/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf
new file mode 100644
index 0000000000..4d79ca3844
--- /dev/null
+++ b/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf
@@ -0,0 +1,47 @@
+## @file
+# Enroll PK, KEK, db, dbx from Default variables
+#
+# Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2021, Semihalf All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.28
+ BASE_NAME = EnrollFromDefaultKeysApp
+ FILE_GUID = 6F18CB2F-1293-4BC1-ABB8-35F84C71812E
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 0.1
+ ENTRY_POINT = UefiMain
+
+[Sources]
+ EnrollFromDefaultKeysApp.c
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[Guids]
+ gEfiCertPkcs7Guid
+ gEfiCertSha256Guid
+ gEfiCertX509Guid
+ gEfiCustomModeEnableGuid
+ gEfiGlobalVariableGuid
+ gEfiImageSecurityDatabaseGuid
+ gEfiSecureBootEnableDisableGuid
+
+[Protocols]
+ gEfiSmbiosProtocolGuid ## CONSUMES
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ SecureBootVariableLib
diff --git a/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.c b/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.c
new file mode 100644
index 0000000000..3407c1c4b9
--- /dev/null
+++ b/SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.c
@@ -0,0 +1,109 @@
+/** @file
+ Enroll default PK, KEK, db, dbx.
+
+Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2021, Semihalf All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/AuthenticatedVariableFormat.h> // gEfiCustomModeEnableGuid
+#include <Guid/GlobalVariable.h> // EFI_SETUP_MODE_NAME
+#include <Guid/ImageAuthentication.h> // EFI_IMAGE_SECURITY_DATABASE
+#include <Library/BaseLib.h> // GUID_STRING_LENGTH
+#include <Library/BaseMemoryLib.h> // CopyGuid()
+#include <Library/DebugLib.h> // ASSERT()
+#include <Library/MemoryAllocationLib.h> // FreePool()
+#include <Library/PrintLib.h> // AsciiSPrint()
+#include <Library/UefiBootServicesTableLib.h> // gBS
+#include <Library/UefiLib.h> // AsciiPrint()
+#include <Library/UefiRuntimeServicesTableLib.h> // gRT
+#include <Uefi/UefiMultiPhase.h>
+#include <Library/SecureBootVariableLib.h>
+
+/**
+ Entry point function of this shell application.
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 SetupMode;
+
+ Status = GetSetupMode (&SetupMode);
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot get SetupMode variable: %r\n", Status);
+ return 1;
+ }
+
+ if (SetupMode == USER_MODE) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Skipped - USER_MODE\n");
+ return 1;
+ }
+
+ Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n", Status);
+ return 1;
+ }
+
+ Status = EnrollDbFromDefault ();
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot enroll db: %r\n", Status);
+ goto error;
+ }
+
+ Status = EnrollDbxFromDefault ();
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot enroll dbt: %r\n", Status);
+ }
+
+ Status = EnrollDbtFromDefault ();
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot enroll dbx: %r\n", Status);
+ }
+
+ Status = EnrollKEKFromDefault ();
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot enroll KEK: %r\n", Status);
+ goto cleardbs;
+ }
+
+ Status = EnrollPKFromDefault ();
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("EnrollFromDefaultKeysApp: Cannot enroll PK: %r\n", Status);
+ goto clearKEK;
+ }
+
+ Status = SetSecureBootMode (STANDARD_SECURE_BOOT_MODE);
+ if (EFI_ERROR (Status)) {
+ AsciiPrint (
+ "EnrollFromDefaultKeysApp: Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
+ "Please do it manually, otherwise system can be easily compromised\n"
+ );
+ }
+ return 0;
+
+clearKEK:
+ DeleteKEK ();
+
+cleardbs:
+ DeleteDbt ();
+ DeleteDbx ();
+ DeleteDb ();
+
+error:
+ Status = SetSecureBootMode (STANDARD_SECURE_BOOT_MODE);
+ if (EFI_ERROR (Status)) {
+ AsciiPrint (
+ "EnrollFromDefaultKeysApp: Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n"
+ "Please do it manually, otherwise system can be easily compromised\n"
+ );
+ }
+
+ return 1;
+}
--
2.25.1


[PATCH v4 5/8] SecurityPkg: Add SecureBootDefaultKeysDxe driver

Grzegorz Bernacki
 

This driver initializes default Secure Boot keys and databases
based on keys embedded in flash.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
Reviewed-by: Sunny Wang <sunny.wang@arm.com>
Reviewed-by: Pete Batard <pete@akeo.ie>
Tested-by: Pete Batard <pete@akeo.ie> on Raspberry Pi
---
SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf | 45 +++++++++++++
SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c | 68 ++++++++++++++++++++
SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.uni | 16 +++++
3 files changed, 129 insertions(+)
create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf
create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c
create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.uni

diff --git a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf
new file mode 100644
index 0000000000..0af7563a3b
--- /dev/null
+++ b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf
@@ -0,0 +1,45 @@
+## @file
+# Initializes Secure Boot default keys
+#
+# Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2021, Semihalf All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecureBootDefaultKeysDxe
+ FILE_GUID = C937FCB7-25AC-4376-89A2-4EA8B317DE83
+ MODULE_TYPE = DXE_DRIVER
+ ENTRY_POINT = SecureBootDefaultKeysEntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+[Sources]
+ SecureBootDefaultKeysDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ DebugLib
+ SecureBootVariableLib
+
+[Guids]
+ ## SOMETIMES_PRODUCES ## Variable:L"PKDefault"
+ ## SOMETIMES_PRODUCES ## Variable:L"KEKDefault"
+ ## SOMETIMES_PRODUCES ## Variable:L"dbDefault"
+ ## SOMETIMES_PRODUCES ## Variable:L"dbtDefault"
+ ## SOMETIMES_PRODUCES ## Variable:L"dbxDefault"
+ gEfiGlobalVariableGuid
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c
new file mode 100644
index 0000000000..12a18dc352
--- /dev/null
+++ b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c
@@ -0,0 +1,68 @@
+/** @file
+ This driver init default Secure Boot variables
+
+Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2021, Semihalf All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Guid/AuthenticatedVariableFormat.h>
+#include <Guid/ImageAuthentication.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SecureBootVariableLib.h>
+
+/**
+ The entry point for SecureBootDefaultKeys driver.
+
+ @param[in] ImageHandle The image handle of the driver.
+ @param[in] SystemTable The system table.
+
+ @retval EFI_ALREADY_STARTED The driver already exists in system.
+ @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of resources.
+ @retval EFI_SUCCESS All the related protocols are installed on the driver.
+ @retval Others Fail to get the SecureBootEnable variable.
+
+**/
+EFI_STATUS
+EFIAPI
+SecureBootDefaultKeysEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SecureBootInitPKDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Cannot initialize PKDefault: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = SecureBootInitKEKDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Cannot initialize KEKDefault: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+ Status = SecureBootInitdbDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Cannot initialize dbDefault: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = SecureBootInitdbtDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: dbtDefault not initialized\n", __FUNCTION__));
+ }
+
+ Status = SecureBootInitdbxDefault ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: dbxDefault not initialized\n", __FUNCTION__));
+ }
+
+ return Status;
+}
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.uni b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.uni
new file mode 100644
index 0000000000..2b6cb7f950
--- /dev/null
+++ b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Provides the capability to intialize Secure Boot default variables
+//
+// Module which initializes Secure boot default variables.
+//
+// Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
+// Copyright (c) 2021, Semihalf All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module which initializes Secure boot default variables"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This module reads embedded keys and initializes Secure Boot default variables."
--
2.25.1


[PATCH v4 4/8] ArmPlatformPkg: Create include file for default key content.

Grzegorz Bernacki
 

This commits add file which can be included by platform Flash
Description File. It allows to specify certificate files, which
will be embedded into binary file. The content of these files
can be used to initialize Secure Boot default keys and databases.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc | 70 ++++++++++++++++++++
1 file changed, 70 insertions(+)
create mode 100644 ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc

diff --git a/ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc b/ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc
new file mode 100644
index 0000000000..bf4f2d42de
--- /dev/null
+++ b/ArmPlatformPkg/SecureBootDefaultKeys.fdf.inc
@@ -0,0 +1,70 @@
+## @file
+# FDF include file which allows to embed Secure Boot keys
+#
+# Copyright (c) 2021, ARM Limited. All rights reserved.
+# Copyright (c) 2021, Semihalf. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+!if $(DEFAULT_KEYS) == TRUE
+ FILE FREEFORM = 85254ea7-4759-4fc4-82d4-5eed5fb0a4a0 {
+ !ifdef $(PK_DEFAULT_FILE)
+ SECTION RAW = $(PK_DEFAULT_FILE)
+ !endif
+ SECTION UI = "PK Default"
+ }
+
+ FILE FREEFORM = 6f64916e-9f7a-4c35-b952-cd041efb05a3 {
+ !ifdef $(KEK_DEFAULT_FILE1)
+ SECTION RAW = $(KEK_DEFAULT_FILE1)
+ !endif
+ !ifdef $(KEK_DEFAULT_FILE2)
+ SECTION RAW = $(KEK_DEFAULT_FILE2)
+ !endif
+ !ifdef $(KEK_DEFAULT_FILE3)
+ SECTION RAW = $(KEK_DEFAULT_FILE3)
+ !endif
+ SECTION UI = "KEK Default"
+ }
+
+ FILE FREEFORM = c491d352-7623-4843-accc-2791a7574421 {
+ !ifdef $(DB_DEFAULT_FILE1)
+ SECTION RAW = $(DB_DEFAULT_FILE1)
+ !endif
+ !ifdef $(DB_DEFAULT_FILE2)
+ SECTION RAW = $(DB_DEFAULT_FILE2)
+ !endif
+ !ifdef $(DB_DEFAULT_FILE3)
+ SECTION RAW = $(DB_DEFAULT_FILE3)
+ !endif
+ SECTION UI = "DB Default"
+ }
+
+ FILE FREEFORM = 36c513ee-a338-4976-a0fb-6ddba3dafe87 {
+ !ifdef $(DBT_DEFAULT_FILE1)
+ SECTION RAW = $(DBT_DEFAULT_FILE1)
+ !endif
+ !ifdef $(DBT_DEFAULT_FILE2)
+ SECTION RAW = $(DBT_DEFAULT_FILE2)
+ !endif
+ !ifdef $(DBT_DEFAULT_FILE3)
+ SECTION RAW = $(DBT_DEFAULT_FILE3)
+ !endif
+ SECTION UI = "DBT Default"
+ }
+
+ FILE FREEFORM = 5740766a-718e-4dc0-9935-c36f7d3f884f {
+ !ifdef $(DBX_DEFAULT_FILE1)
+ SECTION RAW = $(DBX_DEFAULT_FILE1)
+ !endif
+ !ifdef $(DBX_DEFAULT_FILE2)
+ SECTION RAW = $(DBX_DEFAULT_FILE2)
+ !endif
+ !ifdef $(DBX_DEFAULT_FILE3)
+ SECTION RAW = $(DBX_DEFAULT_FILE3)
+ !endif
+ SECTION UI = "DBX Default"
+ }
+
+!endif
--
2.25.1


[PATCH v4 3/8] Intel Platforms: add SecureBootVariableLib class resolution

Grzegorz Bernacki
 

The edk2 patch
SecurityPkg: Create library for setting Secure Boot variables.

removes generic functions from SecureBootConfigDxe and places
them into SecureBootVariableLib. This patch adds SecureBootVariableLib
mapping for each Intel platform which uses SecureBootConfigDxe.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
---
EmulatorPkg/EmulatorPkg.dsc | 1 +
OvmfPkg/Bhyve/BhyveX64.dsc | 1 +
OvmfPkg/OvmfPkgIa32.dsc | 1 +
OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
OvmfPkg/OvmfPkgX64.dsc | 1 +
5 files changed, 5 insertions(+)

diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 20e5468398..966cc7af01 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -132,6 +132,7 @@
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index cbf896e89b..bcc0b2f2f4 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -196,6 +196,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Bhyve/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index f53efeae79..9225966541 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -204,6 +204,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index b3662e17f2..5d53327edb 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -208,6 +208,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 0a237a9058..509acf7926 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -208,6 +208,7 @@
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
!else
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
--
2.25.1

7221 - 7240 of 84490