Skip to content

Commit

Permalink
feat: Add BtG/TXT Register Sanity Check
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Walter <[email protected]>
  • Loading branch information
walterchris committed Jan 23, 2024
1 parent afd1ac7 commit 6ec5dff
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 73 deletions.
22 changes: 22 additions & 0 deletions pkg/provisioning/bootguard/bootguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ func (b *BootGuard) BPMKeyMatchKMHash() (bool, error) {
return true, nil
}

// StrictSaneBPMSecurityProps verifies that BPM contains security properties more strictly
func (b *BootGuard) StrictSaneBPMSecurityProps() (bool, error) {
switch b.Version {
case bgheader.Version10:
Expand Down Expand Up @@ -989,3 +990,24 @@ func (b *BootGuard) ValidateMEAgainstManifests(fws *FirmwareStatus6) (bool, erro
}
return true, nil
}

// Validate if HFSTS1 is sane
func (b *BootGuard) ValidateHFSTS1(fws *FirmwareStatus1) (bool, error) {
if fws.WorkingState != 0x05 {
return false, fmt.Errorf("HFSTS1 working state is not 0x05")
}

if fws.FPTBad {
return false, fmt.Errorf("FPT bad")
}

if fws.MfgMode {
return false, fmt.Errorf("ME is in manufacturing mode")
}

if fws.ErrorCode != 0 {
return false, fmt.Errorf("HFSTS1 error code is not 0")
}

return true, nil
}
138 changes: 138 additions & 0 deletions pkg/provisioning/bootguard/hfsts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package bootguard

import (
"encoding/binary"
"fmt"

"github.com/9elements/go-linux-lowlevel-hw/pkg/hwapi"
)

// Const Array with HFSTS Offsets
var hfstsOffset = []int{0x40, 0x48, 0x60, 0x64, 0x68, 0x6c}

type FirmwareStatus1 struct {
WorkingState uint32
MfgMode bool
FPTBad bool
OperatingState uint32
FWInitComplete bool
FTBUPLoaded bool
FWUpdateInProgress bool
ErrorCode uint32
OperatingMode uint32
ResetCount uint32
BootOptionPresent bool
BISTFinished bool
BISTTestState bool
BISTResetRequest bool
}

type FirmwareStatus6 struct {
ForceACMBootPolicy bool
CPUDebugDisabled bool
BSPInitDisabled bool
ProtectBIOSEnvironment bool
BypassBootPolicy bool
BootPolicyInvalid bool
ErrorEnforcementPolicy uint32
MeasuredBootPolicy bool
VerifiedBootPolicy bool
ACMSVN uint32
KMSVN uint32
BPMSVN uint32
KMID uint32
BootPolicyManifestExecutionStatus bool
Error bool
BootGuardDisable bool
FPFDisable bool
FPFLock bool
TXTSupported bool
}

func GetHFSTS1(hw hwapi.LowLevelHardwareInterfaces) (*FirmwareStatus1, error) {
hfsts1, err := readHFSTSFromPCIConfigSpace(hw, 1)
if err != nil {
return nil, fmt.Errorf("couldn't read HFSTS6 from PCI config space: %v", err)
}

firmwareStatus := FirmwareStatus1{}

configSpace := binary.LittleEndian.Uint32(hfsts1)

firmwareStatus.WorkingState = (configSpace >> 0) & 15
firmwareStatus.MfgMode = (configSpace>>4)&1 != 0
firmwareStatus.FPTBad = (configSpace>>5)&1 != 0
firmwareStatus.OperatingState = (configSpace >> 6) & 7
firmwareStatus.FWInitComplete = (configSpace>>9)&1 != 0
firmwareStatus.FTBUPLoaded = (configSpace>>10)&1 != 0
firmwareStatus.FWUpdateInProgress = (configSpace>>11)&1 != 0
firmwareStatus.ErrorCode = (configSpace >> 12) & 15
firmwareStatus.OperatingMode = (configSpace >> 16) & 15
firmwareStatus.ResetCount = (configSpace >> 20) & 15
firmwareStatus.BootOptionPresent = (configSpace>>24)&1 != 0
firmwareStatus.BISTFinished = (configSpace>>25)&1 != 0
firmwareStatus.BISTTestState = (configSpace>>26)&1 != 0
firmwareStatus.BISTResetRequest = (configSpace>>27)&1 != 0

return &firmwareStatus, nil
}

func GetHFSTS6(hw hwapi.LowLevelHardwareInterfaces) (*FirmwareStatus6, error) {
hfsts6, err := readHFSTSFromPCIConfigSpace(hw, 6)
if err != nil {
return nil, fmt.Errorf("couldn't read HFSTS6 from PCI config space: %v", err)
}

firmwareStatus := FirmwareStatus6{}

configSpace := binary.LittleEndian.Uint32(hfsts6)
firmwareStatus.ForceACMBootPolicy = (configSpace>>0)&1 != 0
firmwareStatus.CPUDebugDisabled = (configSpace>>1)&1 != 0
firmwareStatus.BSPInitDisabled = (configSpace>>2)&1 != 0
firmwareStatus.ProtectBIOSEnvironment = (configSpace>>3)&1 != 0
firmwareStatus.BypassBootPolicy = (configSpace>>4)&1 != 0
firmwareStatus.BootPolicyInvalid = (configSpace>>5)&1 != 0
firmwareStatus.ErrorEnforcementPolicy = (configSpace >> 6) & 3
firmwareStatus.MeasuredBootPolicy = (configSpace>>8)&1 != 0
firmwareStatus.VerifiedBootPolicy = (configSpace>>9)&1 != 0
firmwareStatus.ACMSVN = (configSpace >> 10) & 15
firmwareStatus.KMSVN = (configSpace >> 14) & 15
firmwareStatus.BPMSVN = (configSpace >> 18) & 15
firmwareStatus.KMID = (configSpace >> 22) & 15
firmwareStatus.BootPolicyManifestExecutionStatus = (configSpace>>26)&1 != 0
firmwareStatus.Error = (configSpace>>27)&1 != 0
firmwareStatus.BootGuardDisable = (configSpace>>28)&1 != 0
firmwareStatus.FPFDisable = (configSpace>>29)&1 != 0
firmwareStatus.FPFLock = (configSpace>>30)&1 != 0
firmwareStatus.TXTSupported = (configSpace>>31)&1 != 0

return &firmwareStatus, nil
}

func readHFSTSFromPCIConfigSpace(hw hwapi.LowLevelHardwareInterfaces, offset int) ([]byte, error) {
if offset < 1 || offset > 6 {
return nil, fmt.Errorf("invalid HFSTS offset")
}

var err error
hfsts := make([]byte, 4)
if err := hw.PCIEnumerateVisibleDevices(
func(d hwapi.PCIDevice) (abort bool) {
if (d.Device == IntelCSMEDeviceID && d.Function == IntelFunction) ||
(d.Device == IntelSPSDeviceID && d.Function == IntelFunction) {
hfsts, err = hw.PCIReadConfigSpace(d, hfstsOffset[offset-1], len(hfsts))
if err != nil {
return true
}
return true
}
return false
}); err != nil {
return nil, fmt.Errorf("couldn't enumerate PCI devices")
}
if err != nil {
return nil, fmt.Errorf("couldn't find Intel ME device for runtime checks")
}

return hfsts, nil
}
110 changes: 41 additions & 69 deletions pkg/provisioning/bootguard/me.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package bootguard

import (
"encoding/binary"
"fmt"

"github.com/9elements/converged-security-suite/v2/pkg/tools"
"github.com/9elements/go-linux-lowlevel-hw/pkg/hwapi"
"github.com/linuxboot/fiano/pkg/intel/metadata/common/bgheader"
)
Expand All @@ -14,7 +14,6 @@ const (
IntelSPSDeviceID = 22
IntelBus = 0
IntelFunction = 0
hfsts6Offset = 0x6c

// Boot Guard MSR
BootGuardACMInfoMSR = 0x13a
Expand All @@ -26,28 +25,6 @@ const (
EnforcementPolicyShutdownInThirtyMinutes = 1
)

type FirmwareStatus6 struct {
ForceACMBootPolicy bool
CPUDebugDisabled bool
BSPInitDisabled bool
ProtectBIOSEnvironment bool
BypassBootPolicy bool
BootPolicyInvalid bool
ErrorEnforcementPolicy uint32
MeasuredBootPolicy bool
VerifiedBootPolicy bool
ACMSVN uint32
KMSVN uint32
BPMSVN uint32
KMID uint32
BootPolicyManifestExecutionStatus bool
Error bool
BootGuardDisable bool
FPFDisable bool
FPFLock bool
TXTSupported bool
}

type BGInfo struct {
NEMEnabled bool
TPMType uint64
Expand All @@ -61,51 +38,6 @@ type BGInfo struct {
NoResetSecretProtection bool
}

// GetMEInfo reads bootguard provisioning information from Intel ME
func GetMEInfo(hw hwapi.LowLevelHardwareInterfaces) (*FirmwareStatus6, error) {
var err error
hfsts6 := make([]byte, 4)
if err := hw.PCIEnumerateVisibleDevices(
func(d hwapi.PCIDevice) (abort bool) {
if (d.Device == IntelCSMEDeviceID && d.Function == IntelFunction) ||
(d.Device == IntelSPSDeviceID && d.Function == IntelFunction) {
hfsts6, err = hw.PCIReadConfigSpace(d, hfsts6Offset, len(hfsts6))
if err != nil {
return true
}
return true
}
return false
}); err != nil {
return nil, fmt.Errorf("couldn't enumerate PCI devices")
}
if err != nil {
return nil, fmt.Errorf("couldn't find Intel ME device for runtime checks")
}
var firmwareStatus FirmwareStatus6
configSpace := binary.LittleEndian.Uint32(hfsts6)
firmwareStatus.ForceACMBootPolicy = (configSpace>>0)&1 != 0
firmwareStatus.CPUDebugDisabled = (configSpace>>1)&1 != 0
firmwareStatus.BSPInitDisabled = (configSpace>>2)&1 != 0
firmwareStatus.ProtectBIOSEnvironment = (configSpace>>3)&1 != 0
firmwareStatus.BypassBootPolicy = (configSpace>>4)&1 != 0
firmwareStatus.BootPolicyInvalid = (configSpace>>5)&1 != 0
firmwareStatus.ErrorEnforcementPolicy = (configSpace >> 6) & 3
firmwareStatus.MeasuredBootPolicy = (configSpace>>8)&1 != 0
firmwareStatus.VerifiedBootPolicy = (configSpace>>9)&1 != 0
firmwareStatus.ACMSVN = (configSpace >> 10) & 15
firmwareStatus.KMSVN = (configSpace >> 14) & 15
firmwareStatus.BPMSVN = (configSpace >> 18) & 15
firmwareStatus.KMID = (configSpace >> 22) & 15
firmwareStatus.BootPolicyManifestExecutionStatus = (configSpace>>26)&1 != 0
firmwareStatus.Error = (configSpace>>27)&1 != 0
firmwareStatus.BootGuardDisable = (configSpace>>28)&1 != 0
firmwareStatus.FPFDisable = (configSpace>>29)&1 != 0
firmwareStatus.FPFLock = (configSpace>>30)&1 != 0
firmwareStatus.TXTSupported = (configSpace>>31)&1 != 0
return &firmwareStatus, nil
}

// GetBGInfo reads Boot Guard msr during runtime
func GetBGInfo(hw hwapi.LowLevelHardwareInterfaces) (*BGInfo, error) {
msr := hw.ReadMSR(BootGuardACMInfoMSR)
Expand Down Expand Up @@ -169,3 +101,43 @@ func SaneMEBootGuardProvisioning(v bgheader.BootGuardVersion, fws *FirmwareStatu
}
return true, nil
}

func ValidTXTRegister(hw hwapi.LowLevelHardwareInterfaces) (bool, error) {
txtSpace, err := tools.FetchTXTRegs(hw)
if err != nil {
return false, fmt.Errorf("couldn't fetch TXT regs: %v", err)
}

ACMStatus, err := tools.ReadACMStatus(txtSpace)
if err != nil {
return false, fmt.Errorf("couldn't read ACM status: %v", err)
}

if !ACMStatus.Valid {
return false, fmt.Errorf("ACM status is invalid")
}

if !ACMStatus.ACMStarted {
return false, fmt.Errorf("ACM isn't started")
}

ACMStatusPolicy, err := tools.ReadACMPolicyStatusRaw(txtSpace)
if err != nil {
return false, fmt.Errorf("couldn't read ACM policy status: %v", err)
}

if ((ACMStatusPolicy >> 6) & 0x1) != 0 {
return false, fmt.Errorf("HAP Bit is set")
}

Bootstatus, err := tools.ReadBootStatusRaw(txtSpace)
if err != nil {
return false, fmt.Errorf("couldn't read bootstatus: %v", err)
}

if ((Bootstatus >> 31) & 0x1) != 1 {
return false, fmt.Errorf("BootGuard did not startup successfully")
}

return true, nil
}
30 changes: 26 additions & 4 deletions pkg/test/bootguard_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ var (
SpecificiationTitle: IntelBootGuardSpecificationTitle,
SpecificationDocumentID: IntelBootGuardSpecificationDocumentID,
}
testbootguardtxt = Test{
Name: "[RUNTIME] BtG/TXT registers are sane",
Required: true,
function: BootGuardTXT,
Status: Implemented,
SpecificationChapter: "",
SpecificiationTitle: IntelTXTSpecificationTitle,
SpecificationDocumentID: IntelTXTSpecificationDocumentID,
}

// TestsMemory exposes the slice for memory related txt tests
TestsBootGuard = [...]*Test{
Expand All @@ -94,6 +103,7 @@ var (
&testbootguardibb,
&testbootguardvalidateme,
&testbootguardsanemeconfig,
&testbootguardtxt,
}
)

Expand Down Expand Up @@ -294,11 +304,11 @@ func BootGuardValidateME(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool,
if b == nil || err != nil {
return false, fmt.Errorf("couldn't parse KM and BPM"), err
}
fws, err := bootguard.GetMEInfo(hw)
hfsts6, err := bootguard.GetHFSTS6(hw)
if err != nil {
return false, err, nil
}
valid, err := b.ValidateMEAgainstManifests(fws)
valid, err := b.ValidateMEAgainstManifests(hfsts6)
if !valid || err != nil {
return false, fmt.Errorf("bootguard km/bpm doesn't match ME BootGuard configuration"), err
}
Expand All @@ -322,10 +332,12 @@ func BootGuardSaneMEConfig(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool
if b == nil || err != nil {
return false, fmt.Errorf("couldn't parse KM"), err
}
fws, err := bootguard.GetMEInfo(hw)

hfsts6, err := bootguard.GetHFSTS6(hw)
if err != nil {
return false, err, nil
return false, fmt.Errorf("couldn't read HFSTS6: %v", err), nil
}

bgi, err := bootguard.GetBGInfo(hw)
if err != nil {
return false, err, nil
Expand All @@ -344,3 +356,13 @@ func BootGuardSaneMEConfig(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool
}
return true, nil, nil
}

// BootGuardTXT checks TXT requirements for safe BootGuard configuration
func BootGuardTXT(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool, error, error) {
valid, err := bootguard.ValidTXTRegister(hw)
if !valid || err != nil {
return false, fmt.Errorf("txt regs aren't valid"), err
}

return true, nil, nil
}
Loading

0 comments on commit 6ec5dff

Please sign in to comment.