Merge branch 'master' into meparser

This commit is contained in:
Zaolin 2021-06-22 14:19:51 +02:00 committed by GitHub
commit 91f35e7dd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 157 additions and 30 deletions

View File

@ -13,7 +13,7 @@ jobs:
- checkout
- run: sudo apt install -y golint
# specify any bash command here prefixed with `run: `
- run: GO111MODULE=off go get github.com/tjfoc/gmsm/sm2 github.com/dustin/go-humanize && go run ./pkg/intel/metadata/manifest/common/manifestcodegen/cmd/manifestcodegen -check ./pkg/intel/metadata/manifest ./pkg/intel/metadata/manifest/bootpolicy ./pkg/intel/metadata/manifest/key
- run: GO111MODULE=off go get github.com/tjfoc/gmsm/sm2 github.com/dustin/go-humanize github.com/linuxboot/fiano/pkg/uefi && go run ./pkg/intel/metadata/manifest/common/manifestcodegen/cmd/manifestcodegen -check ./pkg/intel/metadata/manifest ./pkg/intel/metadata/manifest/bootpolicy ./pkg/intel/metadata/manifest/key
- run: if [ "$(gofmt -l .)" != "" ]; then exit 1; fi
- run: golint -set_exit_status ./pkg/test
- run: golint -set_exit_status ./pkg/tools

View File

@ -82,6 +82,7 @@ func (cmd Command) Execute(args []string) {
}
imagePath := args[0]
fianoUEFI.DisableDecompression = false
firmware, err := uefi.ParseUEFIFirmwareFile(imagePath)
assertNoError(err)

View File

@ -3,7 +3,12 @@
package bootpolicy
import (
"bytes"
"fmt"
"github.com/9elements/converged-security-suite/v2/pkg/intel/metadata/manifest"
"github.com/9elements/converged-security-suite/v2/pkg/uefi/consts"
"github.com/linuxboot/fiano/pkg/uefi"
)
// StructInfo is the common header of any element.
@ -27,3 +32,28 @@ type Manifest struct {
func (bpm Manifest) StructInfo() StructInfo {
return bpm.BPMH.StructInfo
}
func (bpm *Manifest) ValidateIBBs(firmware uefi.Firmware) error {
if len(bpm.SE[0].DigestList.List) == 0 {
return fmt.Errorf("no IBB hashes")
}
for _, digest := range bpm.SE[0].DigestList.List {
h, err := digest.HashAlg.Hash()
if err != nil {
return fmt.Errorf("invalid hash function: %v", digest.HashAlg)
}
for _, seg := range bpm.SE[0].IBBSegments {
startIdx := consts.CalculateOffsetFromPhysAddr(uint64(seg.Base), uint64(len(firmware.Buf())))
h.Write(firmware.Buf()[startIdx : startIdx+uint64(seg.Size)])
}
hashValue := h.Sum(nil)
if bytes.Compare(hashValue, digest.HashBuffer) != 0 {
return fmt.Errorf("IBB %s hash mismatch: %X != %X", digest.HashAlg, hashValue, digest.HashBuffer)
}
}
return nil
}

View File

@ -4,14 +4,13 @@ package manifest
import (
"crypto"
"fmt"
"hash"
"strings"
// Required for hash.Hash return in hashInfo struct
_ "crypto/sha1"
_ "crypto/sha256"
_ "crypto/sha512"
"fmt"
"hash"
"strings"
"github.com/tjfoc/gmsm/sm3"
)
@ -41,14 +40,14 @@ const (
)
var hashInfo = []struct {
alg Algorithm
hash hash.Hash
alg Algorithm
hashFactory func() hash.Hash
}{
{AlgSHA1, crypto.SHA1.New()},
{AlgSHA256, crypto.SHA256.New()},
{AlgSHA384, crypto.SHA384.New()},
{AlgSHA512, crypto.SHA512.New()},
{AlgSM3_256, sm3.New()},
{AlgSHA1, crypto.SHA1.New},
{AlgSHA256, crypto.SHA256.New},
{AlgSHA384, crypto.SHA384.New},
{AlgSHA512, crypto.SHA512.New},
{AlgSM3_256, sm3.New},
}
// IsNull returns true if a is AlgNull or zero (unset).
@ -61,10 +60,10 @@ func (a Algorithm) IsNull() bool {
func (a Algorithm) Hash() (hash.Hash, error) {
for _, info := range hashInfo {
if info.alg == a {
if info.hash == nil {
if info.hashFactory == nil {
return nil, fmt.Errorf("go hash algorithm #%snot available", info.alg.String())
}
return info.hash, nil
return info.hashFactory(), nil
}
}
return nil, fmt.Errorf("hash algorithm not supported: %s", a.String())

View File

@ -202,6 +202,11 @@ func (k *Key) PrintKMPubKey(kmAlg Algorithm) error {
}
hash.Write(buf.Bytes())
fmt.Printf(" Key Manifest Pubkey Hash: 0x%x\n", hash.Sum(nil))
// On SKL and KBL the exponent is not included in the KM hash
buf.Truncate(len(k.Data[4:]))
hash.Reset()
hash.Write(buf.Bytes())
fmt.Printf(" Key Manifest Pubkey Hash (Skylake and Kabylake only): 0x%x\n", hash.Sum(nil))
} else {
fmt.Printf(" Key Manifest Pubkey Hash: Unsupported Algorithm\n")
}

View File

@ -79,3 +79,11 @@ type ErrUnexpectedEventType struct {
func (err ErrUnexpectedEventType) Error() string {
return fmt.Sprintf("unexpected event type, reason: '%s'; event: '%#+v'", err.Reason, err.Event)
}
// ErrNoSACM means no S-ACM was found.
type ErrNoSACM struct{}
// Error implements interface `error`.
func (err ErrNoSACM) Error() string {
return fmt.Sprintf("S-ACM not found")
}

View File

@ -91,14 +91,15 @@ func (f Flow) MeasurementIDs() MeasurementIDs {
13 0 4 4 9069CA78E7450A285173431B3E52C5C25299E473 00000000 <- Separator
*/
return MeasurementIDs{
MeasurementIDInit, // is fake measurement
MeasurementIDInit, // is a fake measurement
MeasurementIDACM, // is a fake measurement
MeasurementIDPCR0_DATA,
MeasurementIDPCDFirmwareVendorVersionData,
MeasurementIDPCDFirmwareVendorVersionCode, // is fake measurement
MeasurementIDPCDFirmwareVendorVersionCode, // is a fake measurement
MeasurementIDDXE,
MeasurementIDSeparator,
MeasurementIDFITPointer, // is fake measurement
MeasurementIDFITHeaders, // is fake measurement
MeasurementIDFITPointer, // is a fake measurement
MeasurementIDFITHeaders, // is a fake measurement
}
case FlowIntelLegacyTXTEnabled:
// See also:
@ -108,40 +109,42 @@ func (f Flow) MeasurementIDs() MeasurementIDs {
// * https://www.trustedcomputinggroup.org/wp-content/uploads/PC-ClientSpecific_Platform_Profile_for_TPM_2p0_Systems_v21.pdf (Section 9.3.1)
// * doc/log/ymm03.txt
return MeasurementIDs{
MeasurementIDInit, // is fake measurement
MeasurementIDInit, // is a fake measurement
MeasurementIDACM, // is a fake measurement
MeasurementIDACMDate,
MeasurementIDBIOSStartupModule,
MeasurementIDSCRTMSeparator,
MeasurementIDPCDFirmwareVendorVersionData,
MeasurementIDPCDFirmwareVendorVersionCode, // is fake measurement
MeasurementIDPCDFirmwareVendorVersionCode, // is a fake measurement
MeasurementIDDXE,
MeasurementIDSeparator,
MeasurementIDFITPointer, // is fake measurement
MeasurementIDFITHeaders, // is fake measurement
MeasurementIDFITPointer, // is a fake measurement
MeasurementIDFITHeaders, // is a fake measurement
}
case FlowIntelLegacyTXTEnabledTPM12:
return MeasurementIDs{
MeasurementIDInit, // is fake measurement
MeasurementIDInit, // is a fake measurement
MeasurementIDACM, // is a fake measurement
MeasurementIDACMDateInPlace,
MeasurementIDBIOSStartupModule,
MeasurementIDPCDFirmwareVendorVersionData,
MeasurementIDPCDFirmwareVendorVersionCode, // is fake measurement
MeasurementIDPCDFirmwareVendorVersionCode, // is a fake measurement
MeasurementIDDXE,
MeasurementIDSeparator,
MeasurementIDFITPointer, // is fake measurement
MeasurementIDFITHeaders, // is fake measurement
MeasurementIDFITPointer, // is a fake measurement
MeasurementIDFITHeaders, // is a fake measurement
}
case FlowIntelLegacyTXTDisabled:
return MeasurementIDs{
MeasurementIDPCDFirmwareVendorVersionData,
MeasurementIDPCDFirmwareVendorVersionCode, // is fake measurement
MeasurementIDPCDFirmwareVendorVersionCode, // is a fake measurement
MeasurementIDDXE,
MeasurementIDSeparator,
// Also we include as fake measurements the byte ranges which a known
// to be necessary to correctly parse the firmware.
MeasurementIDFITPointer, // is fake measurement
MeasurementIDFITHeaders, // is fake measurement
MeasurementIDFITPointer, // is a fake measurement
MeasurementIDFITHeaders, // is a fake measurement
}
}
panic(fmt.Sprintf("should not happen: %v", f))

View File

@ -15,15 +15,39 @@ func MeasureInit() *Measurement {
return NewStaticDataMeasurement(MeasurementIDInit, nil)
}
func MeasureACM(fitEntries []fit.Entry) (*Measurement, error) {
m := Measurement{
ID: MeasurementIDACM,
}
mErr := &errors.MultiError{}
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntrySACM: // startup AC module entry
mErr.Add(fitEntry.HeadersErrors...)
m.Data = append(m.Data, *NewRangeDataChunk(0, fitEntry.GetDataOffset(), uint64(len(fitEntry.GetDataBytes()))))
}
}
if len(m.Data) == 0 {
return nil, ErrNoSACM{}
}
return &m, mErr.ReturnValue()
}
func MeasureACMDate(fitEntries []fit.Entry) (*Measurement, error) {
m := Measurement{
ID: MeasurementIDACMDate,
}
mErr := &errors.MultiError{}
found := false
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntrySACM: // startup AC module entry
found = true
mErr.Add(fitEntry.HeadersErrors...)
data, err := fitEntry.ParseData()
@ -41,6 +65,13 @@ func MeasureACMDate(fitEntries []fit.Entry) (*Measurement, error) {
}
}
if !found {
mErr.Add(ErrNoSACM{})
}
if len(m.Data) == 0 {
return nil, mErr.ReturnValue()
}
return &m, mErr.ReturnValue()
}
@ -60,9 +91,11 @@ func MeasureACMDateInPlace(hashAlg manifest.Algorithm, fitEntries []fit.Entry) (
}
mErr := &errors.MultiError{}
found := false
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntrySACM: // startup AC module entry
found = true
mErr.Add(fitEntry.HeadersErrors...)
data, err := fitEntry.ParseData()
@ -81,6 +114,14 @@ func MeasureACMDateInPlace(hashAlg manifest.Algorithm, fitEntries []fit.Entry) (
m.Data = append(m.Data, *NewStaticDataChunk(DataChunkIDUndefined, padding))
}
}
if !found {
mErr.Add(ErrNoSACM{})
}
if len(m.Data) == 0 {
return nil, mErr.ReturnValue()
}
return &m, mErr.ReturnValue()
}

View File

@ -48,6 +48,19 @@ func (chunk DataChunk) String() string {
return string(b)
}
// Find returns the chunk with the specified DataChunkID.
// Or returns nil if such data chunk was not found.
func (s DataChunks) Find(id DataChunkID) *DataChunk {
for idx := range s {
d := &s[idx]
if d.ID == id {
return d
}
}
return nil
}
// Copy performs a deep copy.
func (chunk DataChunk) Copy() *DataChunk {
if chunk.ForceData != nil {
@ -250,6 +263,18 @@ func (s Measurements) AddOffset(offset int64) {
}
}
// Find returns the first measurement with the specified MeasurementID.
// Or returns nil, if such measurement was not found.
func (s Measurements) Find(id MeasurementID) *Measurement {
for _, measurement := range s {
if measurement.ID == id {
return measurement
}
}
return nil
}
// Copy performs a deep copy.
func (s Measurements) Copy() Measurements {
if s == nil {

View File

@ -34,6 +34,7 @@ const (
MeasurementIDUndefined = MeasurementID(iota)
MeasurementIDInit
MeasurementIDPCR0_DATA
MeasurementIDACM
MeasurementIDACMDate
MeasurementIDBIOSStartupModule
MeasurementIDSCRTMSeparator
@ -55,6 +56,8 @@ func (id MeasurementID) IsFake() bool {
return true
case MeasurementIDInit:
return true
case MeasurementIDACM:
return true
case MeasurementIDPCDFirmwareVendorVersionCode:
return true
case MeasurementIDFITPointer:
@ -84,6 +87,8 @@ func (id MeasurementID) String() string {
return "undefined"
case MeasurementIDInit:
return "init"
case MeasurementIDACM:
return "ACM"
case MeasurementIDPCR0_DATA:
return "PCR0_DATA"
case MeasurementIDACMDate:
@ -118,6 +123,8 @@ func (id MeasurementID) PCRIDs() []ID {
return []ID{0}
case MeasurementIDPCR0_DATA:
return []ID{0}
case MeasurementIDACM:
return []ID{0}
case MeasurementIDACMDate:
return []ID{0}
case MeasurementIDACMDateInPlace:
@ -224,6 +231,10 @@ func (id MeasurementID) MeasureFunc() MeasureFunc {
return func(config MeasurementConfig, provider DataProvider) (*Measurement, error) {
return MeasurePCR0Data(config, provider.FITEntries())
}
case MeasurementIDACM:
return func(config MeasurementConfig, provider DataProvider) (*Measurement, error) {
return MeasureACM(provider.FITEntries())
}
case MeasurementIDACMDate:
return func(config MeasurementConfig, provider DataProvider) (*Measurement, error) {
return MeasureACMDate(provider.FITEntries())

View File

@ -39,5 +39,9 @@ func (v ValidateManifests) Validate(firmware Firmware) error {
return fmt.Errorf("key chain is invalid: %w", err)
}
if err := bpm.ValidateIBBs(firmware); err != nil {
return fmt.Errorf("IBB signature in BPM is not valid: %w", err)
}
return nil
}

View File

@ -109,7 +109,7 @@ func TestTXTErrorStatus(t *testing.T) {
if txtErrorStatus.BitSize() != 8 {
t.Errorf("Incorrect BitSize, expected: 64. actual: %v", txtErrorStatus.BitSize())
}
if txtErrorStatus.Address() != registers.TxtPublicSpace+registers.TXTStatusRegisterOffset {
if txtErrorStatus.Address() != registers.TxtPublicSpace+registers.TXTErrorStatusRegisterOffset {
t.Errorf("Incorrect Address, expected: %d. actual: %d",
registers.TxtPublicSpace+registers.TXTStatusRegisterOffset,
txtErrorStatus.Address(),

BIN
testdata/fake_acm/biosacm_cbnt_fake.bin vendored Normal file

Binary file not shown.