Skip to content

Commit

Permalink
Merge branch 'main' into pcr_enable_logging
Browse files Browse the repository at this point in the history
  • Loading branch information
xaionaro authored May 9, 2023
2 parents 108ddfd + e04428e commit 2fefce6
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 40 deletions.
17 changes: 14 additions & 3 deletions pkg/pcr/flow_detection.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,26 @@ func isCBnT(fitEntries []fit.Entry) (bool, error) {
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntryKeyManifestRecord:
data, data2, err := fitEntry.ParseData()
if data == nil && data2 == nil {
_, kmV2, err := fitEntry.ParseData()
// kmV2 is a key manifest of version 2 (which is assumed to correspond to the CBnT version)
if err != nil {
return false, fmt.Errorf("unable to parse KeyManifest policy record: %w", err)
}
if data != nil {
if kmV2 == nil {
// Is a pre-CBnT manifest
return false, nil
}
keyManifestFound = true
case *fit.EntryBootPolicyManifestRecord:
_, bpmV2, err := fitEntry.ParseData()
// bpmV2 is a boot policy manifest of version 2 (which is assumed to correspond to the CBnT version)
if err != nil {
return false, fmt.Errorf("unable to parse BootPolicyManifest: %w", err)
}
if bpmV2 == nil {
// Is a pre-CBnT manifest
return false, nil
}
bootPolicyFound = true
}
}
Expand Down
102 changes: 71 additions & 31 deletions pkg/pcr/get_measurements_pcr0_cbnt0t.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/9elements/converged-security-suite/v2/pkg/registers"
pkgbytes "github.com/linuxboot/fiano/pkg/bytes"
"github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy"
"github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgkey"
"github.com/linuxboot/fiano/pkg/intel/metadata/cbnt"
"github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntbootpolicy"
"github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntkey"
Expand Down Expand Up @@ -71,33 +73,65 @@ func MeasurePCR0Data(config MeasurementConfig, imageSize uint64, fitEntries []fi
Length: uint64(len(acmEntry.GetRSASig())),
}

keyManifest, keyManifestFITEntry, err := getKeyManifest(fitEntries)
kmV1, kmV2, keyManifestFITEntry, err := getKeyManifest(fitEntries)
// kmV1 and kmV2 are key manifests of version 1 (assumably pre-CBnT) and 2 (assumably CBnT).
if err != nil {
return nil, err
}
kmOffset := keyManifestFITEntry.Headers.Address.Offset(imageSize)
data.kmSignature = pkgbytes.Range{
Offset: kmOffset + keyManifest.KeyAndSignatureOffset() + keyManifest.KeyAndSignature.SignatureOffset() + keyManifest.KeyAndSignature.Signature.DataOffset(),
Length: uint64(len(keyManifest.KeyAndSignature.Signature.Data)),
if kmV1 != nil {
data.kmSignature = pkgbytes.Range{
Offset: kmOffset + kmV1.KeyAndSignatureOffset() + kmV1.KeyAndSignature.SignatureOffset() + kmV1.KeyAndSignature.Signature.DataOffset(),
Length: uint64(len(kmV1.KeyAndSignature.Signature.Data)),
}
} else {
data.kmSignature = pkgbytes.Range{
Offset: kmOffset + kmV2.KeyAndSignatureOffset() + kmV2.KeyAndSignature.SignatureOffset() + kmV2.KeyAndSignature.Signature.DataOffset(),
Length: uint64(len(kmV2.KeyAndSignature.Signature.Data)),
}
}

bpManifest, bpManifestFITEntry, err := getBootPolicyManifest(fitEntries)
bpmV1, bpmV2, bpManifestFITEntry, err := getBootPolicyManifest(fitEntries)
// bpmV1 and bpmV2 are boot policy manifests of version 1 (assumably pre-CBnT) and 2 (assumably CBnT).
if err != nil {
return nil, err
}
bpmOffset := bpManifestFITEntry.Headers.Address.Offset(imageSize)
data.bpmSignature = pkgbytes.Range{
Offset: bpmOffset + uint64(bpManifest.KeySignatureOffset) + bpManifest.PMSE.SignatureOffset() + bpManifest.PMSE.Signature.DataOffset(),
Length: uint64(len(bpManifest.PMSE.Signature.Data)),
}

digests := bpManifest.SE[0].DigestList.List
if len(digests) == 0 {
return nil, fmt.Errorf("IBBDigest list is empty")
var (
offsetToTheFirstDigest uint64
digests []cbnt.HashStructure
)
if bpmV1 != nil {
data.bpmSignature = pkgbytes.Range{
Offset: bpmOffset + uint64(bpmV1.PMSEOffset()+bpmV1.PMSE.KeySignatureOffset()) + bpmV1.PMSE.SignatureOffset() + bpmV1.PMSE.Signature.DataOffset(),
Length: uint64(len(bpmV1.PMSE.Signature.Data)),
}
digests = []cbnt.HashStructure{{
HashAlg: cbnt.Algorithm(bpmV1.SE[0].Digest.HashAlg),
HashBuffer: bpmV1.SE[0].Digest.HashBuffer,
}}
if len(digests) == 0 {
return nil, fmt.Errorf("IBBDigest list is empty")
}
// Note: +2 - skip array size field to get the first element
offsetToTheFirstDigest = bpmOffset + bpmV1.SEOffset() +
bpmV1.SE[0].DigestOffset() + 2
} else {
data.bpmSignature = pkgbytes.Range{
Offset: bpmOffset + uint64(bpmV2.KeySignatureOffset) + bpmV2.PMSE.SignatureOffset() + bpmV2.PMSE.Signature.DataOffset(),
Length: uint64(len(bpmV2.PMSE.Signature.Data)),
}

digests = bpmV2.SE[0].DigestList.List
if len(digests) == 0 {
return nil, fmt.Errorf("IBBDigest list is empty")
}
// Note: +2 - skip array size field to get the first element
offsetToTheFirstDigest = bpmOffset + bpmV2.SEOffset() +
bpmV2.SE[0].DigestListOffset() + (bpmV2.SE[0].DigestList.ListOffset() + 2)

}
// Note: +2 - skip array size field to get the first element
offsetToTheFirstDigest := bpmOffset + bpManifest.SEOffset() +
bpManifest.SE[0].DigestListOffset() + (bpManifest.SE[0].DigestList.ListOffset() + 2)
if config.PCR0DataIbbDigestHashAlgorithm == cbnt.AlgUnknown || config.PCR0DataIbbDigestHashAlgorithm == cbnt.AlgNull {
// take the fist element as stated in the doc above
data.ibbDigest = pkgbytes.Range{
Expand Down Expand Up @@ -142,37 +176,38 @@ func getACM(fitEntries []fit.Entry) (*fit.EntrySACMData, *fit.EntrySACM, error)
return nil, nil, fmt.Errorf("ACM FIT entry is not found")
}

func getKeyManifest(fitEntries []fit.Entry) (*cbntkey.Manifest, *fit.EntryKeyManifestRecord, error) {
func getKeyManifest(fitEntries []fit.Entry) (*bgkey.Manifest, *cbntkey.Manifest, *fit.EntryKeyManifestRecord, error) {
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntryKeyManifestRecord:
_, km2, err := fitEntry.ParseData()
if err != nil && km2 != nil {
return nil, nil, err
kmV1, kmV2, err := fitEntry.ParseData()
if err != nil {
return nil, nil, nil, err
}
return km2, fitEntry, nil
return kmV1, kmV2, fitEntry, nil
}
}
return nil, nil, fmt.Errorf("key manifest FIT entry is not found")
return nil, nil, nil, fmt.Errorf("key manifest FIT entry is not found")
}

func getBootPolicyManifest(fitEntries []fit.Entry) (*cbntbootpolicy.Manifest, *fit.EntryBootPolicyManifestRecord, error) {
func getBootPolicyManifest(fitEntries []fit.Entry) (*bgbootpolicy.Manifest, *cbntbootpolicy.Manifest, *fit.EntryBootPolicyManifestRecord, error) {
for _, fitEntry := range fitEntries {
switch fitEntry := fitEntry.(type) {
case *fit.EntryBootPolicyManifestRecord:
_, bpManifest2, err := fitEntry.ParseData()
if err != nil && bpManifest2 != nil {
return nil, nil, err
bpmV1, bpmV2, err := fitEntry.ParseData()
// bpmV1 and bpmV2 are boot policy manifests of version 1 (assumably pre-CBnT) and 2 (assumably CBnT).
if err != nil {
return nil, nil, nil, err
}
return bpManifest2, fitEntry, nil
return bpmV1, bpmV2, fitEntry, nil
}
}
return nil, nil, fmt.Errorf("boot policy manifest FIT entry is not found")
return nil, nil, nil, fmt.Errorf("boot policy manifest FIT entry is not found")
}

// MeasureKeyManifest returns a measurement containing CBnT key cbnt.
func MeasureKeyManifest(imageSize uint64, fitEntries []fit.Entry) (*Measurement, error) {
_, kmFITEntry, err := getKeyManifest(fitEntries)
_, _, kmFITEntry, err := getKeyManifest(fitEntries)
if err != nil {
return nil, fmt.Errorf("unable to get key manifest (KM): %w", err)
}
Expand All @@ -190,7 +225,7 @@ func MeasureKeyManifest(imageSize uint64, fitEntries []fit.Entry) (*Measurement,

// MeasureBootPolicy returns a measurement containing CBnT key cbnt.
func MeasureBootPolicy(imageSize uint64, fitEntries []fit.Entry) (*Measurement, error) {
_, bpmFITEntry, err := getBootPolicyManifest(fitEntries)
_, _, bpmFITEntry, err := getBootPolicyManifest(fitEntries)
if err != nil {
return nil, fmt.Errorf("unable to get boot policy manifest (BPM): %w", err)
}
Expand All @@ -208,15 +243,20 @@ func MeasureBootPolicy(imageSize uint64, fitEntries []fit.Entry) (*Measurement,

// MeasureIBB returns a measurement containing IBB according to BPM.
func MeasureIBB(fitEntries []fit.Entry, firmwareSize uint64) (*Measurement, error) {
bpManifest, _, err := getBootPolicyManifest(fitEntries)
bpManifest1, bpManifest2, _, err := getBootPolicyManifest(fitEntries)
if err != nil {
return nil, fmt.Errorf("unable to get boot policy manifest (BPM): %w", err)
}

result := Measurement{
ID: MeasurementIDIBBFake,
}
ibbRanges := bpManifest.IBBDataRanges(firmwareSize)
var ibbRanges pkgbytes.Ranges
if bpManifest1 != nil {
ibbRanges = bpManifest1.IBBDataRanges(firmwareSize)
} else {
ibbRanges = bpManifest2.IBBDataRanges(firmwareSize)
}
for _, _range := range ibbRanges {
result.Data = append(result.Data, DataChunk{
Range: _range,
Expand Down
20 changes: 14 additions & 6 deletions pkg/pcr/validate_manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,37 @@ func (v ValidateManifests) Validate(firmware Firmware) error {
return fmt.Errorf("unable to parse FIT entries: %w", err)
}

km, kmFIT, err := getKeyManifest(fitEntries)
kmV1, kmV2, kmFIT, err := getKeyManifest(fitEntries)
if err != nil {
return fmt.Errorf("unable to get Key Manifest: %w", err)
}
if kmV1 != nil {
// not supported, yet
return nil
}

if err := km.KeyAndSignature.Verify(kmFIT.DataSegmentBytes[:km.KeyManifestSignatureOffset]); err != nil {
if err := kmV2.KeyAndSignature.Verify(kmFIT.DataSegmentBytes[:kmV2.KeyManifestSignatureOffset]); err != nil {
return fmt.Errorf("unable to confirm KM signature: %w", err)
}

bpm, bpmFIT, err := getBootPolicyManifest(fitEntries)
bpmV1, bpmV2, bpmFIT, err := getBootPolicyManifest(fitEntries)
if err != nil {
return fmt.Errorf("unable to get Boot Policy Manifest: %w", err)
}
if bpmV1 != nil {
// not supported, yet
return nil
}

if err := bpm.PMSE.KeySignature.Verify(bpmFIT.DataSegmentBytes[:bpm.KeySignatureOffset]); err != nil {
if err := bpmV2.PMSE.KeySignature.Verify(bpmFIT.DataSegmentBytes[:bpmV2.KeySignatureOffset]); err != nil {
return fmt.Errorf("unable to confirm KM signature: %w", err)
}

if err := km.ValidateBPMKey(bpm.PMSE.KeySignature); err != nil {
if err := kmV2.ValidateBPMKey(bpmV2.PMSE.KeySignature); err != nil {
return fmt.Errorf("key chain is invalid: %w", err)
}

if err := bpm.ValidateIBB(firmware); err != nil {
if err := bpmV2.ValidateIBB(firmware); err != nil {
return fmt.Errorf("IBB signature in BPM is not valid: %w", err)
}

Expand Down

0 comments on commit 2fefce6

Please sign in to comment.