diff --git a/efi/efi.go b/efi/efi.go index d66ecd85..fc8e4344 100644 --- a/efi/efi.go +++ b/efi/efi.go @@ -19,10 +19,50 @@ package efi +import "github.com/canonical/go-tpm2" + const ( - platformFirmwarePCR = 0 // SRTM, POST BIOS, and Embedded Drivers - driversAndAppsPCR = 2 // UEFI Drivers and UEFI Applications - bootManagerCodePCR = 4 // Boot Manager Code and Boot Attempts PCR - secureBootPCR = 7 // Secure Boot Policy Measurements PCR - kernelConfigPCR = 12 + platformFirmwarePCR tpm2.Handle = 0 // SRTM, POST BIOS, and Embedded Drivers + driversAndAppsPCR tpm2.Handle = 2 // UEFI Drivers and UEFI Applications + bootManagerCodePCR tpm2.Handle = 4 // Boot Manager Code and Boot Attempts PCR + secureBootPolicyPCR tpm2.Handle = 7 // Secure Boot Policy Measurements PCR + kernelConfigPCR tpm2.Handle = 12 ) + +// pcrFlags corresponds to a set of PCRs. This can only represent actual PCRs, it +// cannot represent extendable NV indices (handle type 0x01) if we have a use for +// these in the future +type pcrFlags tpm2.Handle + +func makePcrFlags(pcrs ...tpm2.Handle) pcrFlags { + var out pcrFlags + for _, pcr := range pcrs { + if pcr >= 32 { + panic("invalid PCR") + } + out |= 1 << pcr + } + return out +} + +// PCRs returns a list of all of the PCRs represented by these flags +func (f pcrFlags) PCRs() (out tpm2.HandleList) { + for n := tpm2.Handle(0); n < 32; n++ { + if (f & (1 << n)) > 0 { + out = append(out, n) + } + } + return out +} + +func (f pcrFlags) Contains(pcrs ...tpm2.Handle) bool { + for _, pcr := range pcrs { + if pcr >= 32 { + panic("invalid PCR") + } + if f&(1<= 2.5), without a UEFI debugger enabled and which // measure events in the correct order. - ctx.MeasureVariable(secureBootPCR, efi.GlobalVariable, sbStateName, []byte{1}) + ctx.MeasureVariable(secureBootPolicyPCR, efi.GlobalVariable, sbStateName, []byte{1}) if _, err := h.readAndMeasureSignatureDb(ctx, PK); err != nil { return xerrors.Errorf("cannot measure PK: %w", err) } @@ -101,17 +99,17 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error events = events[1:] switch { - case e.PCRIndex < secureBootPCR && e.EventType == tcglog.EventTypeSeparator: + case e.PCRIndex < tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: // pre-OS to OS-present signal foundOsPresent = true - case e.PCRIndex == secureBootPCR && e.EventType == tcglog.EventTypeSeparator: + case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: // end of secure boot configuration signal if foundSecureBootSeparator { return errors.New("unexpected separator") } - ctx.ExtendPCR(secureBootPCR, tpm2.Digest(e.Digests[ctx.PCRAlg()])) + ctx.ExtendPCR(secureBootPolicyPCR, tpm2.Digest(e.Digests[ctx.PCRAlg()])) foundSecureBootSeparator = true - case e.PCRIndex == secureBootPCR && e.EventType == tcglog.EventTypeEFIVariableAuthority: + case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeEFIVariableAuthority: // secure boot verification event - shouldn't see this before the end of secure // boot configuration signal. if !foundSecureBootSeparator { @@ -119,14 +117,14 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error } digest := tpm2.Digest(e.Digests[ctx.PCRAlg()]) ctx.FwContext().AppendVerificationEvent(digest) - ctx.ExtendPCR(secureBootPCR, digest) - case e.PCRIndex == secureBootPCR && e.EventType == tcglog.EventTypeEFIVariableDriverConfig: + ctx.ExtendPCR(secureBootPolicyPCR, digest) + case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeEFIVariableDriverConfig: // ignore: part of the secure boot configuration - shouldn't see this after the // end of secure boot configuration signal. if foundSecureBootSeparator { return errors.New("unexpected configuration event") } - case e.PCRIndex == secureBootPCR: + case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR): return fmt.Errorf("unexpected event type (%v) found in log", e.EventType) default: // not a secure boot event @@ -144,7 +142,7 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { donePcrReset := false for _, event := range h.log.Events { - if event.PCRIndex != platformFirmwarePCR { + if event.PCRIndex != tcglog.PCRIndex(platformFirmwarePCR) { continue } if event.EventType == tcglog.EventTypeNoAction { @@ -176,10 +174,8 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { } func (h *fwLoadHandler) measureDriversAndApps(ctx pcrBranchContext) { - ctx.ResetPCR(driversAndAppsPCR) - for _, event := range h.log.Events { - if event.PCRIndex != driversAndAppsPCR { + if event.PCRIndex != tcglog.PCRIndex(driversAndAppsPCR) { continue } @@ -191,8 +187,6 @@ func (h *fwLoadHandler) measureDriversAndApps(ctx pcrBranchContext) { } func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) { - ctx.ResetPCR(bootManagerCodePCR) - // Replay the log until the transition to the OS. Different firmware implementations and // configurations perform different pre-OS measurements, and these events need to be preserved // in the profile. @@ -222,7 +216,7 @@ func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) { // OS-present environment, which seems wrong. The approach here assumes that the EDK2 behaviour is // correct. for _, event := range h.log.Events { - if event.PCRIndex != bootManagerCodePCR { + if event.PCRIndex != tcglog.PCRIndex(bootManagerCodePCR) { continue } @@ -239,25 +233,32 @@ func (h *fwLoadHandler) MeasureImageStart(ctx pcrBranchContext) error { return errors.New("the TCG event log does not have the requested algorithm") } - if ctx.Flags()&platformFirmwareProfile > 0 { + // Ensure each PCR in the policy is enabled to its reset value now in case nothing + // extends it later on. We ignore PCR0 here as a special case because it doesn't + // necessarily have a zero reset value. + for _, pcr := range ctx.PCRs().PCRs() { + if pcr == platformFirmwarePCR { + continue + } + ctx.ResetPCR(pcr) + } + + if ctx.PCRs().Contains(platformFirmwarePCR) { if err := h.measurePlatformFirmware(ctx); err != nil { return fmt.Errorf("cannot measure platform firmware policy: %w", err) } } - if ctx.Flags()&driversAndAppsProfile > 0 { + if ctx.PCRs().Contains(driversAndAppsPCR) { h.measureDriversAndApps(ctx) } - if ctx.Flags()&bootManagerCodeProfile > 0 { + if ctx.PCRs().Contains(bootManagerCodePCR) { h.measureBootManagerCodePreOS(ctx) } - if ctx.Flags()&secureBootPolicyProfile > 0 { + if ctx.PCRs().Contains(secureBootPolicyPCR) { if err := h.measureSecureBootPolicyPreOS(ctx); err != nil { return xerrors.Errorf("cannot measure secure boot policy: %w", err) } } - if ctx.Flags()&kernelConfigProfile > 0 { - ctx.ResetPCR(kernelConfigPCR) - } return nil } @@ -306,7 +307,7 @@ func (m *fwImageLoadMeasurer) measureVerification() error { return nil } m.FwContext().AppendVerificationEvent(digest) - m.ExtendPCR(secureBootPCR, digest) + m.ExtendPCR(secureBootPolicyPCR, digest) return nil } @@ -320,13 +321,13 @@ func (m *fwImageLoadMeasurer) measurePEImageDigest() error { } func (m *fwImageLoadMeasurer) measure() error { - if m.Flags()&secureBootPolicyProfile > 0 { + if m.PCRs().Contains(secureBootPolicyPCR) { if err := m.measureVerification(); err != nil { return xerrors.Errorf("cannot measure secure boot event: %w", err) } } - if m.Flags()&bootManagerCodeProfile > 0 { + if m.PCRs().Contains(bootManagerCodePCR) { if err := m.measurePEImageDigest(); err != nil { return xerrors.Errorf("cannot measure boot manager code event: %w", err) } diff --git a/efi/fw_load_handler_test.go b/efi/fw_load_handler_test.go index 8499fa22..6146429a 100644 --- a/efi/fw_load_handler_test.go +++ b/efi/fw_load_handler_test.go @@ -48,15 +48,15 @@ type testFwMeasureImageStartData struct { vars efitest.MockVars logOptions *efitest.LogOptions alg tpm2.HashAlgorithmId - flags PcrProfileFlags + pcrs PcrFlags expectedEvents []*mockPcrBranchEvent } func (s *fwLoadHandlerSuite) testMeasureImageStart(c *C, data *testFwMeasureImageStartData) *FwContext { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(data.vars, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: data.alg, - flags: data.flags}, nil, collector.Next()) + alg: data.alg, + pcrs: data.pcrs}, nil, collector.Next()) handler := NewFwLoadHandler(efitest.NewLog(c, data.logOptions)) c.Check(handler.MeasureImageStart(ctx), IsNil) @@ -74,7 +74,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile(c *C) vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -97,8 +97,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileSecureB Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, SecureBootDisabled: true, }, - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -121,8 +121,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileInclude Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, IncludeDriverLaunch: true, }, - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -143,7 +143,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfile(c *C) { vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, @@ -162,8 +162,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileWithoutC Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, NoCallingEFIApplicationEvent: true, }, - alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, @@ -180,8 +180,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileIncludeS Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, IncludeSysPrepAppLaunch: true, }, - alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4")}, @@ -197,12 +197,12 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyAndBootManager vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile | SecureBootPolicyProfile, + pcrs: MakePcrFlags(BootManagerCodePCR, SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, + {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, - {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: PK, varData: vars[PK].Payload}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: KEK, varData: vars[KEK].Payload}, @@ -217,7 +217,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartPlatformFirmwareProfile(c *C) s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - flags: PlatformFirmwareProfile, + pcrs: MakePcrFlags(PlatformFirmwarePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 0, eventType: mockPcrBranchResetEvent}, {pcr: 0, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6")}, @@ -232,7 +232,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartPlatformFirmwareProfileSL3(c * s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, StartupLocality: 3}, alg: tpm2.HashAlgorithmSHA256, - flags: PlatformFirmwareProfile, + pcrs: MakePcrFlags(PlatformFirmwarePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 0, eventType: mockPcrBranchResetCRTMPCREvent, locality: 3}, {pcr: 0, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6")}, @@ -247,7 +247,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfile(c *C) { s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - flags: DriversAndAppsProfile, + pcrs: MakePcrFlags(DriversAndAppsPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 2, eventType: mockPcrBranchResetEvent}, {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, @@ -259,7 +259,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfile2(c *C) { s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, IncludeDriverLaunch: true}, alg: tpm2.HashAlgorithmSHA256, - flags: DriversAndAppsProfile, + pcrs: MakePcrFlags(DriversAndAppsPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 2, eventType: mockPcrBranchResetEvent}, {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6")}, @@ -272,8 +272,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog1(c *C) { // Insert a second EV_SEPARATOR event into PCR7 collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -296,8 +296,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog2(c *C) { // Prepend a verification event into PCR7 before the EV_SEPARATOR collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -323,8 +323,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog3(c *C) { // Append a configuration event into PCR7 after the EV_SEPARATOR collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -350,8 +350,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog4(c *C) { // Insert an unexpected event type into PCR7 collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -377,8 +377,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog5(c *C) { // Insert an invalid StartupLocality event data into the log collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: PlatformFirmwareProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(PlatformFirmwarePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -402,8 +402,8 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog6(c *C) { // Insert an extra StartupLocality event data into the log collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ - alg: tpm2.HashAlgorithmSHA256, - flags: PlatformFirmwareProfile}, nil, collector.Next()) + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(PlatformFirmwarePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -429,7 +429,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog6(c *C) { type testFwMeasureImageLoadData struct { alg tpm2.HashAlgorithmId - flags PcrProfileFlags + pcrs PcrFlags db efi.SignatureDatabase fc *FwContext image *mockImage @@ -440,7 +440,7 @@ type testFwMeasureImageLoadData struct { func (s *fwLoadHandlerSuite) testMeasureImageLoad(c *C, data *testFwMeasureImageLoadData) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: data.alg, - flags: data.flags, + pcrs: data.pcrs, handlers: s, }, nil, nil) if data.fc != nil { @@ -468,7 +468,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfile(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), expectedEvents: []*mockPcrBranchEvent{ @@ -486,7 +486,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileExisting s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), fc: fc, image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), @@ -496,7 +496,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileExisting func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "bf6b6dfdb1f6435a81e4808db7f846d86d170566e4753d4384fdab6504be4fb9")}, @@ -507,7 +507,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile2(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig3)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "dbffd70a2c43fd2c1931f18b8f8c08c5181db15f996f747dfed34def52fad036")}, @@ -520,7 +520,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyAndBootManagerC s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile | SecureBootPolicyProfile, + pcrs: MakePcrFlags(BootManagerCodePCR, SecureBootPolicyPCR), db: msDb(c), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), expectedEvents: []*mockPcrBranchEvent{ diff --git a/efi/grub_load_handler_test.go b/efi/grub_load_handler_test.go index 1948954f..5af1f4fc 100644 --- a/efi/grub_load_handler_test.go +++ b/efi/grub_load_handler_test.go @@ -42,7 +42,7 @@ var _ = Suite(&grubLoadHandlerSuite{}) func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_7(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -71,7 +71,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_7(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_6(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -100,7 +100,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_6(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShim(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -129,7 +129,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShim(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShimError(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ diff --git a/efi/pcr_branch_context.go b/efi/pcr_branch_context.go index 3825b190..c993efec 100644 --- a/efi/pcr_branch_context.go +++ b/efi/pcr_branch_context.go @@ -36,10 +36,10 @@ type pcrBranchContext interface { FwContext() *fwContext // access the platform firmware state for this branch ShimContext() *shimContext // access the shim state for this branch - ResetPCR(pcr int) // reset the specified PCR for this branch - ResetCRTMPCR(locality uint8) // reset the S-CRTM PCR (0) from the specified locality - ExtendPCR(pcr int, digest tpm2.Digest) // extend the specified PCR for this branch - MeasureVariable(pcr int, guid efi.GUID, name string, data []byte) // measure the specified variable for this branch + ResetPCR(pcr tpm2.Handle) // reset the specified PCR for this branch + ResetCRTMPCR(locality uint8) // reset the S-CRTM PCR (0) from the specified locality + ExtendPCR(pcr tpm2.Handle, digest tpm2.Digest) // extend the specified PCR for this branch + MeasureVariable(pcr tpm2.Handle, guid efi.GUID, name string, data []byte) // measure the specified variable for this branch } type pcrBranchCtx struct { @@ -90,24 +90,24 @@ func (c *pcrBranchCtx) ShimContext() *shimContext { return &c.sc } -func (c *pcrBranchCtx) ResetPCR(pcr int) { - c.branch.AddPCRValue(c.PCRAlg(), pcr, make([]byte, c.PCRAlg().Size())) +func (c *pcrBranchCtx) ResetPCR(pcr tpm2.Handle) { + c.branch.AddPCRValue(c.PCRAlg(), int(pcr), make(tpm2.Digest, c.PCRAlg().Size())) } func (c *pcrBranchCtx) ResetCRTMPCR(locality uint8) { value := make([]byte, c.PCRAlg().Size()) value[len(value)-1] = locality - c.branch.AddPCRValue(c.PCRAlg(), platformFirmwarePCR, value) + c.branch.AddPCRValue(c.PCRAlg(), int(platformFirmwarePCR), value) } -func (c *pcrBranchCtx) ExtendPCR(pcr int, digest tpm2.Digest) { - c.branch.ExtendPCR(c.PCRAlg(), pcr, digest) +func (c *pcrBranchCtx) ExtendPCR(pcr tpm2.Handle, digest tpm2.Digest) { + c.branch.ExtendPCR(c.PCRAlg(), int(pcr), digest) } -func (c *pcrBranchCtx) MeasureVariable(pcr int, guid efi.GUID, name string, data []byte) { +func (c *pcrBranchCtx) MeasureVariable(pcr tpm2.Handle, guid efi.GUID, name string, data []byte) { c.branch.ExtendPCR( c.PCRAlg(), - pcr, + int(pcr), tcglog.ComputeEFIVariableDataDigest(c.PCRAlg().GetHash(), name, guid, data)) } diff --git a/efi/pcr_profile.go b/efi/pcr_profile.go index e9d4c29f..8057245a 100644 --- a/efi/pcr_profile.go +++ b/efi/pcr_profile.go @@ -33,10 +33,31 @@ type PCRProfileOption interface { applyOptionTo(gen *pcrProfileGenerator) } -type pcrProfileSetFlagsOption pcrProfileFlags +// PCRProfileEnablePCRsOption is an option for AddPCRProfile that adds one or more PCRs. +type PCRProfileEnablePCRsOption interface { + PCRProfileOption + PCRs() tpm2.HandleList +} + +type pcrProfileSetPcrsOption struct { + PCRProfileOption + pcrs pcrFlags +} + +func newPcrProfileSetPcrsOption(pcrs pcrFlags) *pcrProfileSetPcrsOption { + out := &pcrProfileSetPcrsOption{ + pcrs: pcrs, + } + out.PCRProfileOption = out + return out +} -func (o pcrProfileSetFlagsOption) applyOptionTo(gen *pcrProfileGenerator) { - gen.flags |= pcrProfileFlags(o) +func (o *pcrProfileSetPcrsOption) applyOptionTo(gen *pcrProfileGenerator) { + gen.pcrs |= o.pcrs +} + +func (o *pcrProfileSetPcrsOption) PCRs() tpm2.HandleList { + return o.pcrs.PCRs() } // WithPlatformFirmwareProfile adds the SRTM, POST BIOS and Embedded Drivers @@ -46,15 +67,15 @@ func (o pcrProfileSetFlagsOption) applyOptionTo(gen *pcrProfileGenerator) { // It is suitable in environments where platform firmware is measured by a // hardware root of trust as opposed to being verified as authentic and prevented // from running otherwise. -func WithPlatformFirmwareProfile() PCRProfileOption { - return pcrProfileSetFlagsOption(platformFirmwareProfile) +func WithPlatformFirmwareProfile() PCRProfileEnablePCRsOption { + return newPcrProfileSetPcrsOption(makePcrFlags(platformFirmwarePCR)) } // WithDriversAndAppsProfile adds the UEFI Drivers and UEFI Applications profile // (measured to PCR2). This is copied directly from the current host environment // configiguration. -func WithDriversAndAppsProfile() PCRProfileOption { - return pcrProfileSetFlagsOption(driversAndAppsProfile) +func WithDriversAndAppsProfile() PCRProfileEnablePCRsOption { + return newPcrProfileSetPcrsOption(makePcrFlags(driversAndAppsPCR)) } // WithSecureBootPolicyProfile requests that the UEFI secure boot policy profile is @@ -113,8 +134,8 @@ func WithDriversAndAppsProfile() PCRProfileOption { // (before the EV_SEPARATOR events are measured to PCRs 0-6). Note that the inclusion // of these makes a policy inherently fragile because it is not possible to pre-generate // policy to accomodate updates of these components. -func WithSecureBootPolicyProfile() PCRProfileOption { - return pcrProfileSetFlagsOption(secureBootPolicyProfile) +func WithSecureBootPolicyProfile() PCRProfileEnablePCRsOption { + return newPcrProfileSetPcrsOption(makePcrFlags(secureBootPolicyPCR)) } // WithBootManagerCodeProfile requests that the UEFI boot manager code and boot attempts @@ -149,8 +170,8 @@ func WithSecureBootPolicyProfile() PCRProfileOption { // will be invalid if the platform firmware performs boot attempts that subsequently // fail before performing a successful attempt, even if the images associated with the // successful attempt are included in this policy. -func WithBootManagerCodeProfile() PCRProfileOption { - return pcrProfileSetFlagsOption(bootManagerCodeProfile) +func WithBootManagerCodeProfile() PCRProfileEnablePCRsOption { + return newPcrProfileSetPcrsOption(makePcrFlags(bootManagerCodePCR)) } // WithKernelConfigProfile adds the kernel config profile. This binds a policy to a @@ -160,8 +181,8 @@ func WithBootManagerCodeProfile() PCRProfileOption { // Kernel commandlines can be injected into the profile with [KernelCommandlineParams]. // Snap models can be injected into the profile with [SnapModelParams]. Note that a model // assertion is mandatory for profiles that include a UKI for Ubuntu Core. -func WithKernelConfigProfile() PCRProfileOption { - return pcrProfileSetFlagsOption(kernelConfigProfile) +func WithKernelConfigProfile() PCRProfileEnablePCRsOption { + return newPcrProfileSetPcrsOption(makePcrFlags(kernelConfigPCR)) } // AddPCRProfile adds a profile defined by the supplied options to the supplied @@ -171,23 +192,13 @@ func WithKernelConfigProfile() PCRProfileOption { func AddPCRProfile(pcrAlg tpm2.HashAlgorithmId, branch *secboot_tpm2.PCRProtectionProfileBranch, loadSequences *ImageLoadSequences, options ...PCRProfileOption) error { gen := newPcrProfileGenerator(pcrAlg, loadSequences, options...) - if gen.flags == 0 { + if gen.pcrs == 0 { return errors.New("must specify a profile to add") } return gen.addPCRProfile(branch) } -type pcrProfileFlags int - -const ( - platformFirmwareProfile pcrProfileFlags = 1 << iota - driversAndAppsProfile - bootManagerCodeProfile - secureBootPolicyProfile - kernelConfigProfile -) - type pcrProfileGenerator struct { // pcrAlg is the PCR digest algorithm to add to the profile. pcrAlg tpm2.HashAlgorithmId @@ -205,8 +216,8 @@ type pcrProfileGenerator struct { // profile. handlers imageLoadHandlerMap - // flags is used to specify additional options for profile generation. - flags pcrProfileFlags + // pcrs is used to specify the PCRs to generate profiles for. + pcrs pcrFlags // varModifiers is a set of callbacks that can apply customizations to // EFI variables supplied from the HostEnvironment. This creates a sequence @@ -305,9 +316,9 @@ func (g *pcrProfileGenerator) PCRAlg() tpm2.HashAlgorithmId { return g.pcrAlg } -// Flags implements pcrProfileContext.Flags. -func (g *pcrProfileGenerator) Flags() pcrProfileFlags { - return g.flags +// PCRS implements pcrProfileContext.PCRs. +func (g *pcrProfileGenerator) PCRs() pcrFlags { + return g.pcrs } func (g *pcrProfileGenerator) ImageLoadHandlerMap() imageLoadHandlerMap { @@ -317,7 +328,7 @@ func (g *pcrProfileGenerator) ImageLoadHandlerMap() imageLoadHandlerMap { // pcrProfileContext corresponds to the global environment of an EFI PCR profile generation. type pcrProfileContext interface { PCRAlg() tpm2.HashAlgorithmId // the PCR digest algorithm for the profile - Flags() pcrProfileFlags + PCRs() pcrFlags ImageLoadHandlerMap() imageLoadHandlerMap } diff --git a/efi/pcr_profile_test.go b/efi/pcr_profile_test.go index c102e078..9ec6f5e2 100644 --- a/efi/pcr_profile_test.go +++ b/efi/pcr_profile_test.go @@ -86,12 +86,12 @@ func (s *pcrProfileMockedSuite) TestPcrProfileGeneratorPCRAlgSHA1(c *C) { func (s *pcrProfileMockedSuite) TestWithSecureBootPolicyProfile(c *C) { gen := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA256, NewImageLoadSequences(), WithSecureBootPolicyProfile()) - c.Check(gen.Flags(), Equals, SecureBootPolicyProfile) + c.Check(gen.PCRs(), Equals, PcrFlags(1< 0 { + if m.PCRs().Contains(secureBootPolicyPCR) { if err := m.measureVerification(); err != nil { return xerrors.Errorf("cannot measure secure boot event: %w", err) } } - if m.Flags()&bootManagerCodeProfile > 0 { + if m.PCRs().Contains(bootManagerCodePCR) { if err := m.measurePEImageDigest(); err != nil { return xerrors.Errorf("cannot measure boot manager code event: %w", err) } diff --git a/efi/shim_load_handler_test.go b/efi/shim_load_handler_test.go index 7f3846e1..40eb769d 100644 --- a/efi/shim_load_handler_test.go +++ b/efi/shim_load_handler_test.go @@ -231,7 +231,7 @@ func (s *shimLoadHandlerSuite) TestNewShimLoadHandlerWithVendorDb15_6(c *C) { type testShimMeasureImageStartData struct { alg tpm2.HashAlgorithmId - flags PcrProfileFlags + pcrs PcrFlags vars efitest.MockVars shimFlags ShimFlags vendorDb *SecureBootDB @@ -241,7 +241,7 @@ type testShimMeasureImageStartData struct { func (s *shimLoadHandlerSuite) testMeasureImageStart(c *C, data *testShimMeasureImageStartData) (PcrBranchContext, *RootVarsCollector) { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(data.vars, nil)) - ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: data.alg, flags: data.flags}, nil, collector.Next()) + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: data.alg, pcrs: data.pcrs}, nil, collector.Next()) handler := &ShimLoadHandler{ Flags: data.shimFlags, @@ -259,7 +259,7 @@ func (s *shimLoadHandlerSuite) testMeasureImageStart(c *C, data *testShimMeasure func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_6(c *C) { _, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2021030218\n"))), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -280,7 +280,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileApply // the profile with. ctx, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2021030218\n")), withSbatPolicy(ShimSbatPolicyLatest)), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -330,7 +330,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileUpgra // and verify that we get new sets of initial variables to rerun the profile with. ctx, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2021030218\n"))), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimVendorCertContainsDb | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -364,7 +364,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_7T // current SbatLevel. _, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2022052400\ngrub,2\n"))), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec, vendorDb: &SecureBootDB{ @@ -382,9 +382,9 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_7T func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_2(c *C) { // Test MeasureImageStart on a pre-SBAT shim _, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, - vars: makeMockVars(c, withMsSecureBootConfig()), + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR), + vars: makeMockVars(c, withMsSecureBootConfig()), vendorDb: &SecureBootDB{ Name: efi.VariableDescriptor{Name: "Shim", GUID: ShimGuid}, Contents: efi.SignatureDatabase{efitest.NewSignatureListX509(c, canonicalCACert, efi.GUID{})}, @@ -398,7 +398,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_2T // and verify we get new sets of initial variables to rerun the profile with. ctx, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), vars: makeMockVars(c, withMsSecureBootConfig()), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -430,7 +430,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile15_2T func (s *shimLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfile(c *C) { _, collector := s.testMeasureImageStart(c, &testShimMeasureImageStartData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), vars: makeMockVars(c, withMsSecureBootConfig()), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -444,7 +444,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfile(c *C) type testShimMeasureImageLoadData struct { alg tpm2.HashAlgorithmId - flags PcrProfileFlags + pcrs PcrFlags db efi.SignatureDatabase shimFlags ShimFlags vendorDb *SecureBootDB @@ -456,7 +456,7 @@ type testShimMeasureImageLoadData struct { func (s *shimLoadHandlerSuite) testMeasureImageLoad(c *C, data *testShimMeasureImageLoadData) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: data.alg, - flags: data.flags, + pcrs: data.pcrs, handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -486,7 +486,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfile15_7(c s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimVendorCertContainsDb | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -506,7 +506,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfile15_6(c s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -526,7 +526,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileVendor s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimVendorCertContainsDb | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -546,7 +546,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileVerify s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, + pcrs: MakePcrFlags(SecureBootPolicyPCR), db: msDb(c), shimFlags: ShimHasSbatVerification | ShimFixVariableAuthorityEventsMatchSpec | ShimHasSbatRevocationManagement, vendorDb: &SecureBootDB{ @@ -565,9 +565,9 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileVerify verificationDigest := testutil.DecodeHexString(c, "533f27695c8a3bdf2994bdca61291ae5edf781da051f592649270e82d7c95dc1") s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ - alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile, - db: msDb(c), + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(SecureBootPolicyPCR), + db: msDb(c), vendorDb: &SecureBootDB{ Name: efi.VariableDescriptor{Name: "Shim", GUID: ShimGuid}, Contents: efi.SignatureDatabase{efitest.NewSignatureListX509(c, canonicalCACert, efi.GUID{})}, @@ -583,7 +583,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileVerify func (s *shimLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) { s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, grubUbuntuSig3)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3709c5a882490fa5b9b7a471f3466341da4267060419491954324d3bfb6aa0c6")}, @@ -594,7 +594,7 @@ func (s *shimLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) func (s *shimLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile2(c *C) { s.testMeasureImageLoad(c, &testShimMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - flags: BootManagerCodeProfile, + pcrs: MakePcrFlags(BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, grubUbuntuSig2)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "6f007fb8b3a8397bbbe5aa4d64ad2624c2cfb7cd5fa18d51bfbb0f27d1d62b89")}, diff --git a/efi/uc_uki_load_handler.go b/efi/uc_uki_load_handler.go index bee84fdd..e79ca86a 100644 --- a/efi/uc_uki_load_handler.go +++ b/efi/uc_uki_load_handler.go @@ -40,7 +40,7 @@ func (h *ubuntuCoreUKILoadHandler) MeasureImageStart(ctx pcrBranchContext) error // less interesting for us. Note that this would require some additional work // because the systemd-pcrphase is disabled at the moment. - if ctx.Flags()&kernelConfigProfile > 0 { + if ctx.PCRs().Contains(kernelConfigPCR) { // the stub doesn't measure anything if the commandline is empty if ctx.Params().KernelCommandline != "" { ctx.ExtendPCR(kernelConfigPCR, @@ -53,7 +53,7 @@ func (h *ubuntuCoreUKILoadHandler) MeasureImageStart(ctx pcrBranchContext) error // TODO: handle sysexts if we need them in the future, which go to the sysext PCR (13). - if ctx.Flags()&kernelConfigProfile > 0 { + if ctx.PCRs().Contains(kernelConfigPCR) { if ctx.Params().SnapModel == nil { return errors.New("snap model must be set using SnapModelParams") } diff --git a/efi/uc_uki_load_handler_test.go b/efi/uc_uki_load_handler_test.go index 206d4217..6ebc8b34 100644 --- a/efi/uc_uki_load_handler_test.go +++ b/efi/uc_uki_load_handler_test.go @@ -33,14 +33,14 @@ var _ = Suite(&ucUkiLoadHandlerSuite{}) type testUCUKIMeasureImageStartParams struct { alg tpm2.HashAlgorithmId - flags PcrProfileFlags + pcrs PcrFlags params LoadParams expectedEvents []*mockPcrBranchEvent } func (s *ucUkiLoadHandlerSuite) testMeasureImageStart(c *C, params *testUCUKIMeasureImageStartParams) { - ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: params.alg, flags: params.flags}, ¶ms.params, nil) + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: params.alg, pcrs: params.pcrs}, ¶ms.params, nil) var handler UbuntuCoreUKILoadHandler c.Check(handler.MeasureImageStart(ctx), IsNil) @@ -49,8 +49,8 @@ func (s *ucUkiLoadHandlerSuite) testMeasureImageStart(c *C, params *testUCUKIMea func (s *ucUkiLoadHandlerSuite) TestMeasureImageStart(c *C) { s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ - alg: tpm2.HashAlgorithmSHA256, - flags: KernelConfigProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(KernelConfigPCR), params: LoadParams{ KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ @@ -71,8 +71,8 @@ func (s *ucUkiLoadHandlerSuite) TestMeasureImageStart(c *C) { func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartDifferentCommandline(c *C) { s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ - alg: tpm2.HashAlgorithmSHA256, - flags: KernelConfigProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(KernelConfigPCR), params: LoadParams{ KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=recover", SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ @@ -93,8 +93,8 @@ func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartDifferentCommandline(c *C) func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartDifferentModel(c *C) { s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ - alg: tpm2.HashAlgorithmSHA256, - flags: KernelConfigProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(KernelConfigPCR), params: LoadParams{ KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ @@ -131,8 +131,8 @@ func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoKernelConfig(c *C) { func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartSHA1(c *C) { s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ - alg: tpm2.HashAlgorithmSHA1, - flags: KernelConfigProfile, + alg: tpm2.HashAlgorithmSHA1, + pcrs: MakePcrFlags(KernelConfigPCR), params: LoadParams{ KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ @@ -153,8 +153,8 @@ func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartSHA1(c *C) { func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoCommandline(c *C) { s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ - alg: tpm2.HashAlgorithmSHA256, - flags: KernelConfigProfile, + alg: tpm2.HashAlgorithmSHA256, + pcrs: MakePcrFlags(KernelConfigPCR), params: LoadParams{ SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ "authority-id": "fake-brand", @@ -172,7 +172,7 @@ func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoCommandline(c *C) { } func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoSnapModel(c *C) { - ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: tpm2.HashAlgorithmSHA256, flags: KernelConfigProfile}, nil, nil) + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: tpm2.HashAlgorithmSHA256, pcrs: MakePcrFlags(KernelConfigPCR)}, nil, nil) var handler UbuntuCoreUKILoadHandler c.Check(handler.MeasureImageStart(ctx), ErrorMatches, `snap model must be set using SnapModelParams`) diff --git a/go.mod b/go.mod index feb17558..4ef8e2dc 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/canonical/go-sp800.108-kdf v0.0.0-20210315104021-ead800bbf9a0 github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3 github.com/canonical/go-tpm2 v1.3.0 - github.com/canonical/tcglog-parser v0.0.0-20230929123437-16b3d8d08691 + github.com/canonical/tcglog-parser v0.0.0-20240502135731-7e805de2ca0d github.com/snapcore/snapd v0.0.0-20220714152900-4a1f4c93fc85 golang.org/x/crypto v0.9.0 - golang.org/x/sys v0.8.0 + golang.org/x/sys v0.19.0 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.3.0 @@ -22,6 +22,7 @@ require ( github.com/kr/pretty v0.2.2-0.20200810074440-814ac30b4b18 // indirect github.com/kr/text v0.1.0 // indirect github.com/snapcore/go-gettext v0.0.0-20191107141714-82bbea49e785 // indirect + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect golang.org/x/net v0.10.0 // indirect gopkg.in/retry.v1 v1.0.3 // indirect gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect diff --git a/go.sum b/go.sum index 9caf132b..b6ab10e2 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/canonical/go-tpm2 v1.3.0/go.mod h1:kLkR1//7ocrPDl6LZfijTKEoPGxRIZSbb8 github.com/canonical/tcglog-parser v0.0.0-20210824131805-69fa1e9f0ad2/go.mod h1:QoW2apR2tBl6T/4czdND/EHjL1Ia9cCmQnIj9Xe0Kt8= github.com/canonical/tcglog-parser v0.0.0-20230929123437-16b3d8d08691 h1:EMZbYZXGGmtSaS2+DIza1gZ54+KVjzsw/NEUAY8me1E= github.com/canonical/tcglog-parser v0.0.0-20230929123437-16b3d8d08691/go.mod h1:EPlw+kpcTgSHXkLiUP/Jqp4CmkNPyVnJLAk4oSjNFrQ= +github.com/canonical/tcglog-parser v0.0.0-20240502135731-7e805de2ca0d h1:bLkGnvu8xqC6OTceF41KLsX/R/mOzvgMpqgJKAywgiM= +github.com/canonical/tcglog-parser v0.0.0-20240502135731-7e805de2ca0d/go.mod h1:e2KTSzgMF5y6ThtfLnNJT0FwqfQUPmannJy5MnAZ1js= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/frankban/quicktest v1.2.2 h1:xfmOhhoH5fGPgbEAlhLpJH9p0z/0Qizio9osmvn9IUY= @@ -66,6 +68,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= @@ -78,6 +82,8 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=