diff --git a/efi/fw_load_handler.go b/efi/fw_load_handler.go index 6cfa0fd1..86c63f61 100644 --- a/efi/fw_load_handler.go +++ b/efi/fw_load_handler.go @@ -423,18 +423,33 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { } func (h *fwLoadHandler) measureDriversAndApps(ctx pcrBranchContext) error { + seenSeparator := false + for _, event := range h.log.Events { if event.PCRIndex != internal_efi.DriversAndAppsPCR { continue } if event.EventType == tcglog.EventTypeSeparator { - return h.measureSeparator(ctx, internal_efi.DriversAndAppsPCR, event) + if seenSeparator { + return errors.New("more than one separator in log") + } + if err := h.measureSeparator(ctx, internal_efi.DriversAndAppsPCR, event); err != nil { + return err + } + seenSeparator = true + continue } + + // Some firmware measures vendor events here after the separator, + // and this profile is a copy of the log, so keep copying. ctx.ExtendPCR(internal_efi.DriversAndAppsPCR, event.Digests[ctx.PCRAlg()]) } - return errors.New("missing separator in log") + if !seenSeparator { + return errors.New("missing separator in log") + } + return nil } func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) error { diff --git a/efi/fw_load_handler_test.go b/efi/fw_load_handler_test.go index fdb4a3ff..aa04dccd 100644 --- a/efi/fw_load_handler_test.go +++ b/efi/fw_load_handler_test.go @@ -992,6 +992,19 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfile2(c *C) { }) } +func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfileVendorEventAfterSeparator(c *C) { + s.testMeasureImageStart(c, &testFwMeasureImageStartData{ + logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, IncludeVendorEventAfterSeparator: true}, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(internal_efi.DriversAndAppsPCR), + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 2, eventType: mockPcrBranchResetEvent}, + {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, // EV_SEPARATOR + {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a")}, // vendor event, SHA-256 of 0x01 + }, + }) +} + func (s *fwLoadHandlerSuite) TestMeasureImageStartErrDisallowDMAProtectionDisabled(c *C) { collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ diff --git a/internal/efitest/log.go b/internal/efitest/log.go index d9d59a11..f13cc511 100644 --- a/internal/efitest/log.go +++ b/internal/efitest/log.go @@ -191,6 +191,7 @@ type LogOptions struct { NoSBAT bool // omit the SbatLevel measurement to mimic older versions of shim PreOSVerificationUsesDigests crypto.Hash // Whether Driver or SysPrep launches are verified using a digest DisableDeployedMode bool // Whether deployed/audit modes are disabled and we have UEFI 2.5 + IncludeVendorEventAfterSeparator bool // include a vendor-defined event in PCR2 after the pre-OS to OS-present transition } // NewLog creates a mock TCG log for testing. The log will look like a standard @@ -666,6 +667,15 @@ func NewLog(c *C, opts *LogOptions) *tcglog.Log { maybeMeasureDMAProtectionDisabledEvent(c, builder, opts, DMAProtectionDisabledEventOrderAfterSeparator) } + // Mock a vendor-defined event measured to PCR2 after the transition to OS-present. + if opts.IncludeVendorEventAfterSeparator { + data := tcglog.OpaqueEventData([]byte{0x01}) + builder.hashLogExtendEvent(c, data, &logEvent{ + pcrIndex: 2, + eventType: tcglog.EventType(0x8401), + data: data}) + } + // Mock firmware application launch if opts.IncludeOSPresentFirmwareAppLaunch != zeroGuid { pe := bytesHashData(opts.IncludeOSPresentFirmwareAppLaunch[:])