diff --git a/cmd/bg-suite/cmd.go b/cmd/bg-suite/cmd.go index dc7beb9a..643104fc 100644 --- a/cmd/bg-suite/cmd.go +++ b/cmd/bg-suite/cmd.go @@ -51,7 +51,7 @@ func (e *execTestsCmd) Run(ctx *context) error { ret := false data, err := os.ReadFile(e.Firmware) if err != nil { - return fmt.Errorf("can't read firmware file") + return fmt.Errorf("can't read firmware file %v", e.Firmware) } preset := test.PreSet{ Firmware: data, diff --git a/go.mod b/go.mod index f14dc89b..28f4b682 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/xaionaro-go/bytesextra v0.0.0-20220103144954-846e454ddea9 github.com/xaionaro-go/unhash v0.0.0-20230427202706-0195a574c620 github.com/xaionaro-go/unsafetools v0.0.0-20210722164218-75ba48cf7b3c + go.uber.org/multierr v1.11.0 golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 56d5c864..60dda104 100644 --- a/go.sum +++ b/go.sum @@ -472,6 +472,8 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= diff --git a/pkg/provisioning/bootguard/bootguard.go b/pkg/provisioning/bootguard/bootguard.go index 01ae9797..626cbeb5 100644 --- a/pkg/provisioning/bootguard/bootguard.go +++ b/pkg/provisioning/bootguard/bootguard.go @@ -20,6 +20,7 @@ import ( "github.com/linuxboot/fiano/pkg/intel/metadata/fit" "github.com/linuxboot/fiano/pkg/uefi" "github.com/tidwall/pretty" + "go.uber.org/multierr" ) // Everything more secure than SHA-1 @@ -93,7 +94,7 @@ func NewVData(vdata VersionedData) (*BootGuard, error) { b.Version, _ = bgheader.DetectBGV(manifest) } if b.Version == 0 { - return nil, fmt.Errorf("NewVData: can't identify bootguard header") + return nil, fmt.Errorf("NewVData: can't identify BootGuard header") } b.VData = vdata return &b, nil @@ -123,7 +124,7 @@ func NewBPM(bpm io.ReadSeeker) (*BootGuard, error) { return nil, err } default: - return nil, fmt.Errorf("NewBPM: can't identify bootguard header") + return nil, fmt.Errorf("NewBPM: can't identify BootGuard header") } return &b, nil } @@ -152,7 +153,7 @@ func NewKM(km io.ReadSeeker) (*BootGuard, error) { return nil, err } default: - return nil, fmt.Errorf("NewKM: can't identify bootguard header") + return nil, fmt.Errorf("NewKM: can't identify BootGuard header") } return &b, nil } @@ -172,7 +173,7 @@ func NewBPMAndKM(bpm io.ReadSeeker, km io.ReadSeeker) (*BootGuard, error) { return nil, err } if bpmV != kmV { - return nil, fmt.Errorf("km and bpm version number differ") + return nil, fmt.Errorf("Key Manifest and Boot Policy Manifest version number differ") } b.Version = bpmV switch b.Version { @@ -199,7 +200,7 @@ func NewBPMAndKM(bpm io.ReadSeeker, km io.ReadSeeker) (*BootGuard, error) { return nil, err } default: - return nil, fmt.Errorf("NewBPMAndKM: can't identify bootguard header") + return nil, fmt.Errorf("NewBPMAndKM: can't identify BootGuard header") } return &b, nil } @@ -242,7 +243,7 @@ func NewBPMAndKMFromBIOS(biosFilepath string, jsonFilepath *os.File) (*BootGuard return nil, err } default: - return nil, fmt.Errorf("NewBPMAndKMFromBIOS: can't identify bootguard header") + return nil, fmt.Errorf("NewBPMAndKMFromBIOS: can't identify BootGuard header") } data, err := json.Marshal(b.VData) if err != nil { @@ -264,11 +265,11 @@ func (b *BootGuard) ValidateBPM() error { case bgheader.Version20: return b.VData.CBNTbpm.Validate() default: - return fmt.Errorf("ValidateBPM: can't identify bootguard header") + return fmt.Errorf("ValidateBPM: can't identify BootGuard header") } } -// ValidateKM reads from a binary source, parses into the key manifest structure +// ValidateKM reads from a binary source, parses into the Key Manifest structure // and validates the structure func (b *BootGuard) ValidateKM() error { switch b.Version { @@ -277,7 +278,7 @@ func (b *BootGuard) ValidateKM() error { case bgheader.Version20: return b.VData.CBNTkm.Validate() default: - return fmt.Errorf("ValidateKM: can't identify bootguard header") + return fmt.Errorf("ValidateKM: can't identify BootGuard header") } } @@ -289,11 +290,11 @@ func (b *BootGuard) PrintBPM() { case bgheader.Version20: b.VData.CBNTbpm.Print() default: - fmt.Println("PrintBPM: can't identify bootguard header") + fmt.Println("PrintBPM: can't identify BootGuard header") } } -// PrintKM prints the key manifest in human readable +// PrintKM prints the Key Manifest in human readable func (b *BootGuard) PrintKM() { switch b.Version { case bgheader.Version10: @@ -301,11 +302,11 @@ func (b *BootGuard) PrintKM() { case bgheader.Version20: b.VData.CBNTkm.Print() default: - fmt.Println("PrintKM: can't identify bootguard header") + fmt.Println("PrintKM: can't identify BootGuard header") } } -// WriteKM returns a key manifest as bytes in format defined in #575623. +// WriteKM returns a Key Manifest as bytes in format defined in #575623. func (b *BootGuard) WriteKM() ([]byte, error) { var err error buf := new(bytes.Buffer) @@ -315,7 +316,7 @@ func (b *BootGuard) WriteKM() ([]byte, error) { case bgheader.Version20: _, err = b.VData.CBNTkm.WriteTo(buf) default: - fmt.Println("WriteKM: can't identify bootguard header") + fmt.Println("WriteKM: can't identify BootGuard header") } return buf.Bytes(), err } @@ -330,7 +331,7 @@ func (b *BootGuard) WriteBPM() ([]byte, error) { case bgheader.Version20: _, err = b.VData.BGbpm.WriteTo(buf) default: - fmt.Println("WriteBPM: can't identify bootguard header") + fmt.Println("WriteBPM: can't identify BootGuard header") } return buf.Bytes(), err } @@ -360,7 +361,7 @@ func (b *BootGuard) ReadJSON(filepath string) error { return nil } -// StitchKM returns a key manifest manifest as byte slice +// StitchKM returns a Key Manifest as byte slice func (b *BootGuard) StitchKM(pubKey crypto.PublicKey, signature []byte) ([]byte, error) { switch b.Version { case bgheader.Version10: @@ -380,7 +381,7 @@ func (b *BootGuard) StitchKM(pubKey crypto.PublicKey, signature []byte) ([]byte, return nil, err } default: - fmt.Println("StitchKM: can't identify bootguard header") + fmt.Println("StitchKM: can't identify BootGuard header") } return b.WriteKM() } @@ -409,7 +410,7 @@ func (b *BootGuard) StitchBPM(pubKey crypto.PublicKey, signature []byte) ([]byte return nil, err } default: - fmt.Println("StitchBPM: can't identify bootguard header") + fmt.Println("StitchBPM: can't identify BootGuard header") } return b.WriteBPM() } @@ -447,7 +448,7 @@ func (b *BootGuard) SignKM(signAlgo string, privkey crypto.PrivateKey) ([]byte, return nil, err } default: - fmt.Println("SignKM: can't identify bootguard header") + fmt.Println("SignKM: can't identify BootGuard header") } return b.WriteKM() } @@ -487,7 +488,7 @@ func (b *BootGuard) SignBPM(signAlgo string, privkey crypto.PrivateKey) ([]byte, return nil, err } default: - fmt.Println("SignBPM: can't identify bootguard header") + fmt.Println("SignBPM: can't identify BootGuard header") } return b.WriteKM() } @@ -513,7 +514,7 @@ func (b *BootGuard) VerifyKM() error { return err } default: - fmt.Println("VerifyKM: can't identify bootguard header") + fmt.Println("VerifyKM: can't identify BootGuard header") } return nil } @@ -539,7 +540,7 @@ func (b *BootGuard) VerifyBPM() error { return err } default: - fmt.Println("VerifyBPM: can't identify bootguard header") + fmt.Println("VerifyBPM: can't identify BootGuard header") } return nil } @@ -615,7 +616,7 @@ func (b *BootGuard) CalculateNEMSize(image []byte, acm *tools.ACM) (uint16, erro } return uint16(cbntbootpolicy.NewSize4K(totalSize)), nil default: - return 0, fmt.Errorf("CalculateNEMSize: can't identify bootguard header") + return 0, fmt.Errorf("CalculateNEMSize: can't identify BootGuard header") } } @@ -673,7 +674,7 @@ func (b *BootGuard) GetBPMPubHash(pubkey crypto.PublicKey, hashAlgo string) erro } b.VData.CBNTkm.Hash = append(keyHashes, kH) default: - fmt.Println("can't identify bootguard header") + fmt.Println("can't identify BootGuard header") } return nil } @@ -757,7 +758,7 @@ func (b *BootGuard) GetIBBsDigest(image []byte, hashAlgo string) (digest []byte, } digest = hash.Sum(nil) default: - fmt.Println("can't identify bootguard header") + fmt.Println("can't identify BootGuard header") } return digest, nil } @@ -787,62 +788,70 @@ func (b *BootGuard) GenerateBPMFromImage(biosFilepath string) (*BootGuard, error copy(b.VData.CBNTbpm.SE[0].DigestList.List[iterator].HashBuffer, d) } default: - fmt.Println("can't identify bootguard header") + fmt.Println("can't identify BootGuard header") } return b, nil } // BPMCryptoSecure verifies that BPM uses sane crypto algorithms func (b *BootGuard) BPMCryptoSecure() (bool, error) { + var errs error switch b.Version { case bgheader.Version10: hash := b.VData.BGbpm.SE[0].Digest.HashAlg if hash == bg.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("signed IBB hash in BPM uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("signed IBB hash in BPM uses insecure hash algorithm SHA1 or has none")) } hash = b.VData.BGbpm.PMSE.Signature.HashAlg if hash == bg.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("BPM signature uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("BPM signature uses insecure hash algorithm SHA1 or has none")) } case bgheader.Version20: for _, hash := range b.VData.CBNTbpm.SE[0].DigestList.List { if hash.HashAlg == cbnt.AlgSHA1 || hash.HashAlg.IsNull() { if b.VData.CBNTbpm.SE[0].DigestList.Size < 2 { - return false, fmt.Errorf("signed IBB hash list in BPM uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("signed IBB hash list in BPM uses insecure hash algorithm SHA1 or has none")) } } } hash := b.VData.CBNTbpm.PMSE.Signature.HashAlg if hash == cbnt.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("BPM signature uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("BPM signature uses insecure hash algorithm SHA1 or has none")) } } + if errs != nil { + return false, fmt.Errorf("%+v", errs) + } return true, nil } // KMCryptoSecure verifies that KM uses sane crypto algorithms func (b *BootGuard) KMCryptoSecure() (bool, error) { + var errs error switch b.Version { case bgheader.Version10: hash := b.VData.BGkm.KeyAndSignature.Signature.HashAlg if hash == bg.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("KM signature uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest signature uses insecure hash algorithm SHA1 or has none")) } hash = b.VData.BGkm.BPKey.HashAlg if hash == bg.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("signed BPM hash in KM uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("signed BPM hash in Key Manifest uses insecure hash algorithm SHA1 or has none")) } case bgheader.Version20: hash := b.VData.CBNTkm.PubKeyHashAlg if hash == cbnt.AlgSHA1 || hash.IsNull() { - return false, fmt.Errorf("KM signature uses insecure hash algorithm SHA1/Null") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest signature uses insecure hash algorithm SHA1 or has none")) } for _, hash := range b.VData.CBNTkm.Hash { if hash.Digest.HashAlg == cbnt.AlgSHA1 || hash.Digest.HashAlg.IsNull() { - return false, fmt.Errorf("the KM hash %s uses insecure hash algorithm SHA1/Null", hash.Usage.String()) + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest hash %s uses insecure hash algorithm SHA1 or has none", hash.Usage.String())) } } } + if errs != nil { + return false, fmt.Errorf("%+v", errs) + } return true, nil } @@ -862,7 +871,7 @@ func (b *BootGuard) KMHasBPMHash() (bool, error) { } } if !bpmHashFound { - return false, fmt.Errorf("couldn't find BPM hash in KM") + return false, fmt.Errorf("couldn't find BPM hash in Key Manifest") } return true, nil } @@ -873,14 +882,14 @@ func (b *BootGuard) BPMKeyMatchKMHash() (bool, error) { case bgheader.Version10: if b.VData.BGkm.BPKey.HashBufferTotalSize() > minHashTypeSize { if err := b.VData.BGkm.ValidateBPMKey(b.VData.BGbpm.PMSE.KeySignature); err != nil { - return false, fmt.Errorf("couldn't verify bpm hash in km") + return false, fmt.Errorf("couldn't verify BPM hash in Key Manifest") } } case bgheader.Version20: for _, hash := range b.VData.CBNTkm.Hash { if hash.Usage == cbntkey.UsageBPMSigningPKD { if err := b.VData.CBNTkm.ValidateBPMKey(b.VData.CBNTbpm.PMSE.KeySignature); err != nil { - return false, fmt.Errorf("couldn't verify bpm hash in km") + return false, fmt.Errorf("couldn't verify BPM hash in Key Manifest") } } } @@ -890,58 +899,71 @@ func (b *BootGuard) BPMKeyMatchKMHash() (bool, error) { // StrictSaneBPMSecurityProps verifies that BPM contains security properties more strictly func (b *BootGuard) StrictSaneBPMSecurityProps() (bool, error) { + var errs error + switch b.Version { case bgheader.Version10: flags := b.VData.BGbpm.SE[0].Flags if !flags.AuthorityMeasure() { - return false, fmt.Errorf("pcr-7 data should extended for OS security") + errs = multierr.Append(errs, fmt.Errorf("PCR-7 data should extended for OS security")) } if !flags.TPMFailureLeavesHierarchiesEnabled() { - return false, fmt.Errorf("tpm failure should lead to default measurements from PCR0 to PCR7") + errs = multierr.Append(errs, fmt.Errorf("TPM failure should lead to default measurements from PCR0 to PCR7")) } case bgheader.Version20: bgFlags := b.VData.CBNTbpm.SE[0].Flags if !bgFlags.AuthorityMeasure() { - return false, fmt.Errorf("pcr-7 data should extended for OS security") + errs = multierr.Append(errs, fmt.Errorf("PCR-7 data should extended for OS security")) } if !bgFlags.TPMFailureLeavesHierarchiesEnabled() { - return false, fmt.Errorf("tpm failure should lead to default measurements from PCR0 to PCR7") + errs = multierr.Append(errs, fmt.Errorf("TPM failure should lead to default measurements from PCR0 to PCR7")) } txtFlags := b.VData.CBNTbpm.TXTE.ControlFlags if txtFlags.MemoryScrubbingPolicy() != cbntbootpolicy.MemoryScrubbingPolicySACM { - return false, fmt.Errorf("S-ACM memory scrubbing should be used over the BIOS") + errs = multierr.Append(errs, fmt.Errorf("S-ACM memory scrubbing should be used over the BIOS")) } } - + if errs != nil { + return false, errs + } return b.SaneBPMSecurityProps() } // SaneBPMSecurityProps verifies that BPM contains security properties set accordingly to spec func (b *BootGuard) SaneBPMSecurityProps() (bool, error) { + var errs error + switch b.Version { case bgheader.Version10: flags := b.VData.BGbpm.SE[0].Flags if !flags.DMAProtection() { - return false, fmt.Errorf("dma protection should be enabled for bootguard") + errs = multierr.Combine(errs, fmt.Errorf("DMA protection should be enabled for BootGuard")) } if b.VData.BGbpm.SE[0].PBETValue.PBETValue() == 0 { - return false, fmt.Errorf("firmware shall not allowed to run infinitely after incident happened") + errs = multierr.Combine(errs, fmt.Errorf("firmware shall not allowed to run infinitely after incident happened")) } case bgheader.Version20: bgFlags := b.VData.CBNTbpm.SE[0].Flags if !bgFlags.DMAProtection() { if b.VData.CBNTbpm.SE[0].DMAProtBase0 == 0 && b.VData.CBNTbpm.SE[0].VTdBAR == 0 { - return false, fmt.Errorf("dma protection should be enabled for bootguard") + errs = multierr.Combine(errs, fmt.Errorf("DMA protection should be enabled for BootGuard")) } } if b.VData.CBNTbpm.SE[0].PBETValue.PBETValue() == 0 { - return false, fmt.Errorf("firmware shall not allowed to run infinitely after incident happened") + errs = multierr.Combine(errs, fmt.Errorf("firmware should not be allowed to run infinitely after incident happened")) + } + pm := b.VData.BGbpm + if pm == nil { + errs = multierr.Combine(errs, fmt.Errorf("no BootGuard Boot Policy Manifest found")) } txtFlags := b.VData.CBNTbpm.TXTE.ControlFlags if !txtFlags.IsSACMRequestedToExtendStaticPCRs() { - return false, fmt.Errorf("S-ACM shall always extend static PCRs") + errs = multierr.Combine(errs, fmt.Errorf("S-ACM shall always extend static PCRs")) } } + if errs != nil { + return false, fmt.Errorf("%+v", errs) + } return true, nil } @@ -954,11 +976,11 @@ func (b *BootGuard) IBBsMatchBPMDigest(image []byte) (bool, error) { switch b.Version { case bgheader.Version10: if err := b.VData.BGbpm.ValidateIBB(firmware); err != nil { - return false, fmt.Errorf("bpm final ibb hash doesn't match selected measurements in image") + return false, fmt.Errorf("BPM final IBB hash doesn't match selected measurements in image") } case bgheader.Version20: if err := b.VData.CBNTbpm.ValidateIBB(firmware); err != nil { - return false, fmt.Errorf("bpm final ibb hash doesn't match selected measurements in image") + return false, fmt.Errorf("BPM final IBB hash doesn't match selected measurements in image") } } return true, nil @@ -966,28 +988,32 @@ func (b *BootGuard) IBBsMatchBPMDigest(image []byte) (bool, error) { // ValidateMEAgainstManifests validates during runtime ME configuation with BootGuard KM & BPM manifests func (b *BootGuard) ValidateMEAgainstManifests(fws *FirmwareStatus6) (bool, error) { + var errs error switch b.Version { case bgheader.Version10: if fws.BPMSVN != uint32(b.VData.BGbpm.BPMSVN) { - return false, fmt.Errorf("bpm svn doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Boot Policy Manifest SVN doesn't match ME configuration")) } if fws.KMSVN != uint32(b.VData.BGkm.KMSVN) { - return false, fmt.Errorf("km svn doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest SVN doesn't match ME configuration")) } if fws.KMID != uint32(b.VData.BGkm.KMID) { - return false, fmt.Errorf("km KMID doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest ID doesn't match ME configuration")) } case bgheader.Version20: if fws.BPMSVN > uint32(b.VData.CBNTbpm.BPMSVN) { - return false, fmt.Errorf("bpm svn doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Boot Policy Manifest SVN doesn't match ME configuration")) } if fws.KMSVN != uint32(b.VData.CBNTkm.KMSVN) { - return false, fmt.Errorf("km svn doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest SVN doesn't match ME configuration")) } if fws.KMID != uint32(b.VData.CBNTkm.KMID) { - return false, fmt.Errorf("km KMID doesn't match me configuration") + errs = multierr.Combine(errs, fmt.Errorf("Key Manifest ID doesn't match ME configuration")) } } + if errs != nil { + return false, fmt.Errorf("%+v", errs) + } return true, nil } diff --git a/pkg/test/bootguard_tests.go b/pkg/test/bootguard_tests.go index 7f6291ca..3eca2bf0 100644 --- a/pkg/test/bootguard_tests.go +++ b/pkg/test/bootguard_tests.go @@ -8,6 +8,7 @@ import ( "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/fit" + "go.uber.org/multierr" ) const ( @@ -26,40 +27,40 @@ var ( SpecificationDocumentID: IntelFITSpecificationDocumentID, } testbootguardacm = Test{ - Name: "SACM meets sane BootGuard requirements", - Required: true, - function: BootGuardACM, - dependencies: []*Test{&testbootguardfit}, + Name: "SACM meets sane BootGuard requirements", + Required: true, + function: BootGuardACM, + // dependencies: []*Test{&testbootguardfit}, Status: Implemented, SpecificationChapter: "Chapter A. Authenticated Code Modules", SpecificiationTitle: IntelTXTSpecificationTitle, SpecificationDocumentID: IntelTXTSpecificationDocumentID, } testbootguardkm = Test{ - Name: "Key Manifest meets sane BootGuard requirements", - Required: true, - function: BootGuardKM, - dependencies: []*Test{&testbootguardfit}, + Name: "Key Manifest meets sane BootGuard requirements", + Required: true, + function: BootGuardKM, + // dependencies: []*Test{&testbootguardfit}, Status: Implemented, SpecificationChapter: "", SpecificiationTitle: IntelBootGuardSpecificationTitle, SpecificationDocumentID: IntelBootGuardSpecificationDocumentID, } testbootguardbpm = Test{ - Name: "Boot Policy Manifest meets sane BootGuard requirements", - Required: true, - function: BootGuardBPM, - dependencies: []*Test{&testbootguardfit}, + Name: "Boot Policy Manifest meets sane BootGuard requirements", + Required: true, + function: BootGuardBPM, + // dependencies: []*Test{&testbootguardfit}, Status: Implemented, SpecificationChapter: "", SpecificiationTitle: IntelBootGuardSpecificationTitle, SpecificationDocumentID: IntelBootGuardSpecificationDocumentID, } testbootguardibb = Test{ - Name: "Verifies BPM and IBBs match firmware image", - Required: true, - function: BootGuardIBB, - dependencies: []*Test{&testbootguardfit}, + Name: "Verifies BPM and IBBs match firmware image", + Required: true, + function: BootGuardIBB, + // dependencies: []*Test{&testbootguardfit}, Status: Implemented, SpecificationChapter: "", SpecificiationTitle: IntelBootGuardSpecificationTitle, @@ -230,19 +231,20 @@ func BootGuardBPM(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool, error, bpmReader = bytes.NewReader(entry.DataSegmentBytes) } } + var errs error b, err := bootguard.NewBPMAndKM(bpmReader, kmReader) if b == nil || err != nil { - return false, fmt.Errorf("couldn't parse KM and BPM"), err + errs = multierr.Combine(errs, fmt.Errorf("couldn't parse KM and BPM\n")) } if err := b.ValidateBPM(); err != nil { - return false, fmt.Errorf("couldn't validate BPM"), err + errs = multierr.Combine(errs, fmt.Errorf("couldn't validate BPM")) } if err := b.VerifyBPM(); err != nil { - return false, fmt.Errorf("couldn't verify BPM signature"), err + errs = multierr.Combine(errs, fmt.Errorf("couldn't verify BPM signature")) } secure, err := b.BPMCryptoSecure() if !secure || err != nil { - return false, fmt.Errorf("bpm crypto parameters are insecure"), err + errs = multierr.Combine(errs, fmt.Errorf("bpm crypto parameters are insecure")) } if p.Strict { secure, err = b.StrictSaneBPMSecurityProps() @@ -250,11 +252,14 @@ func BootGuardBPM(hw hwapi.LowLevelHardwareInterfaces, p *PreSet) (bool, error, secure, err = b.SaneBPMSecurityProps() } if !secure || err != nil { - return false, fmt.Errorf("bpm hasn't sane security properties"), err + errs = multierr.Combine(errs, fmt.Errorf("bpm hasn't sane security properties: %v", err)) } secure, err = b.BPMKeyMatchKMHash() if !secure || err != nil { - return false, fmt.Errorf("bpm doesn't match km hash"), err + errs = multierr.Combine(errs, fmt.Errorf("bpm doesn't match km hash: %v", err)) + } + if errs != nil { + return false, fmt.Errorf("multiple errors"), fmt.Errorf("%+v", errs) } return true, nil, nil } diff --git a/pkg/test/test.go b/pkg/test/test.go index 0cf54ff9..d6fe763f 100644 --- a/pkg/test/test.go +++ b/pkg/test/test.go @@ -111,7 +111,7 @@ func (t *Test) Run(hw hwapi.LowLevelHardwareInterfaces, preset *PreSet) bool { } t.Result = ResultFail } else if testerror != nil && internalerror != nil { - t.ErrorText = testerror.Error() + ": " + internalerror.Error() + t.ErrorText = fmt.Sprintf("\n %v:\n %+v\n", testerror.Error(), internalerror) if t.SpecificiationTitle != "" || t.SpecificationDocumentID != "" { t.ErrorTextSpec = "Please have a look at " if t.SpecificiationTitle != "" {