diff --git a/efi/efi.go b/efi/efi.go index fc8e4344..4815ed1b 100644 --- a/efi/efi.go +++ b/efi/efi.go @@ -22,11 +22,7 @@ package efi import "github.com/canonical/go-tpm2" const ( - 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 + kernelConfigPCR tpm2.Handle = 12 ) // pcrFlags corresponds to a set of PCRs. This can only represent actual PCRs, it diff --git a/efi/efi_test.go b/efi/efi_test.go index c317115b..5be3c25a 100644 --- a/efi/efi_test.go +++ b/efi/efi_test.go @@ -33,6 +33,7 @@ import ( . "gopkg.in/check.v1" . "github.com/snapcore/secboot/efi" + "github.com/snapcore/secboot/efi/internal" "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" ) @@ -693,61 +694,79 @@ type efiSuite struct{} var _ = Suite(&efiSuite{}) func (s *efiSuite) TestMakePcrFlags1(c *C) { - flags := MakePcrFlags(SecureBootPolicyPCR) - c.Check(flags, Equals, PcrFlags(1< 0 } -// Next returns the next starting state to generate a profile branch for. This will -// not return the same starting state more than once. -func (c *rootVarsCollector) Next() *varBranch { +// Next returns the next starting set to generate a profile branch for. This will +// not return the same starting set more than once. +func (c *variableSetCollector) Next() *varBranch { next := c.todo[0] c.todo = c.todo[1:] return c.newVarBranch(next) } -// PeekAll returns all of the pending starting states to generate profile -// branches for. -func (c *rootVarsCollector) PeekAll() []*varBranch { +// PeekAll returns all of the pending starting sets to generate profile +// branches for, without consuming them. It allows them to be added to +// with options that run before the profile generation. +func (c *variableSetCollector) PeekAll() []*varBranch { var out []*varBranch for _, r := range c.todo { out = append(out, c.newVarBranch(r)) } return out } - -type rootVarsModifier func(*rootVarsCollector) error diff --git a/efi/env_test.go b/efi/env_test.go index 1a4ac8e2..cbf75556 100644 --- a/efi/env_test.go +++ b/efi/env_test.go @@ -33,12 +33,12 @@ type envSuite struct{} var _ = Suite(&envSuite{}) -func (s *envSuite) TestRootVarReaderReadVar(c *C) { +func (s *envSuite) TestInitialVarReaderReadVar(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "SecureBoot", GUID: efi.GlobalVariable}: {Payload: []byte{1}, Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) data, attrs, err := reader.ReadVar("SecureBoot", efi.GlobalVariable) c.Check(err, IsNil) @@ -46,12 +46,12 @@ func (s *envSuite) TestRootVarReaderReadVar(c *C) { c.Check(attrs, Equals, efi.AttributeBootserviceAccess|efi.AttributeRuntimeAccess) } -func (s *envSuite) TestRootVarReaderApplyOneUpdate(c *C) { +func (s *envSuite) TestInitialVarReaderApplyOneUpdate(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates(NewVarUpdate(nil, efi.VariableDescriptor{Name: "foo", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{2})) data, attrs, err := reader.ReadVar("foo", testGuid1) @@ -60,12 +60,12 @@ func (s *envSuite) TestRootVarReaderApplyOneUpdate(c *C) { c.Check(attrs, Equals, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess) } -func (s *envSuite) TestRootVarReaderApplyMultipleUpdates(c *C) { +func (s *envSuite) TestInitialVarReaderApplyMultipleUpdates(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates( NewVarUpdate( NewVarUpdate(nil, efi.VariableDescriptor{Name: "bar", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{5}), @@ -82,12 +82,12 @@ func (s *envSuite) TestRootVarReaderApplyMultipleUpdates(c *C) { c.Check(attrs, Equals, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess) } -func (s *envSuite) TestRootVarReaderApplyUpdatesOrdering(c *C) { +func (s *envSuite) TestInitialVarReaderApplyUpdatesOrdering(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates( NewVarUpdate( NewVarUpdate(nil, efi.VariableDescriptor{Name: "foo", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{2}), @@ -99,61 +99,61 @@ func (s *envSuite) TestRootVarReaderApplyUpdatesOrdering(c *C) { c.Check(attrs, Equals, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess) } -func (s *envSuite) TestRootVarReaderKey(c *C) { +func (s *envSuite) TestInitialVarReaderKey(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) - c.Check(reader.Key(), DeepEquals, RootVarReaderKey{}) + reader := NewInitialVarReader(env) + c.Check(reader.Key(), DeepEquals, InitialVarReaderKey{}) } -func (s *envSuite) TestRootVarReaderKeyWithOneUpdate(c *C) { +func (s *envSuite) TestInitialVarReaderKeyWithOneUpdate(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates(NewVarUpdate(nil, efi.VariableDescriptor{Name: "foo", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{2})) - var expected RootVarReaderKey + var expected InitialVarReaderKey copy(expected[:], testutil.DecodeHexString(c, "af83642902c9f89dc8f761bb03a29bae54cc648e")) c.Check(reader.Key(), DeepEquals, expected) } -func (s *envSuite) TestRootVarReaderKeyWithMultipleUpdates(c *C) { +func (s *envSuite) TestInitialVarReaderKeyWithMultipleUpdates(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates( NewVarUpdate( NewVarUpdate(nil, efi.VariableDescriptor{Name: "bar", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{5}), efi.VariableDescriptor{Name: "foo", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{2})) - var expected RootVarReaderKey + var expected InitialVarReaderKey copy(expected[:], testutil.DecodeHexString(c, "d9d3425d3e48666ff1ffc66d211b4bbe2dc654ae")) c.Check(reader.Key(), DeepEquals, expected) } -func (s *envSuite) TestRootVarReaderKeyOmitsUnchanged(c *C) { +func (s *envSuite) TestInitialVarReaderKeyOmitsUnchanged(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates(NewVarUpdate(nil, efi.VariableDescriptor{Name: "foo", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{1})) - c.Check(reader.Key(), DeepEquals, RootVarReaderKey{}) + c.Check(reader.Key(), DeepEquals, InitialVarReaderKey{}) } -func (s *envSuite) TestRootVarReaderCopy(c *C) { +func (s *envSuite) TestInitialVarReaderCopy(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil) - reader := NewRootVarReader(env) + reader := NewInitialVarReader(env) reader.ApplyUpdates( NewVarUpdate( NewVarUpdate(nil, efi.VariableDescriptor{Name: "bar", GUID: testGuid1}, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{5}), @@ -195,7 +195,7 @@ type testRootVarsCollectorData struct { } func (s *envSuite) testRootVarsCollector(c *C, data *testRootVarsCollectorData) { - collector := NewRootVarsCollector(data.env) + collector := NewVariableSetCollector(data.env) c.Assert(collector, NotNil) for i, expected := range data.expected { @@ -531,7 +531,7 @@ func (s *envSuite) TestRootVarsCollectorPeekAll(c *C) { {Name: "SecureBoot", GUID: efi.GlobalVariable}: {Payload: []byte{1}, Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess}, }, nil) - collector := NewRootVarsCollector(env) + collector := NewVariableSetCollector(env) c.Assert(collector, NotNil) roots := collector.PeekAll() @@ -559,7 +559,7 @@ func (s *envSuite) TestRootVarsCollectorPeekAll(c *C) { func (s *envSuite) TestVarBranchReadsUpdate(c *C) { env := efitest.NewMockHostEnvironment(efitest.MockVars{}, nil) - collector := NewRootVarsCollector(env) + collector := NewVariableSetCollector(env) root := collector.Next() c.Check(root.WriteVar("foo", testGuid1, efi.AttributeNonVolatile|efi.AttributeBootserviceAccess, []byte{1}), IsNil) diff --git a/efi/export_test.go b/efi/export_test.go index 31189d73..983d2f15 100644 --- a/efi/export_test.go +++ b/efi/export_test.go @@ -22,16 +22,13 @@ package efi import ( efi "github.com/canonical/go-efilib" "github.com/canonical/tcglog-parser" + "github.com/snapcore/secboot/efi/internal" ) // Export constants for testing const ( - BootManagerCodePCR = bootManagerCodePCR - DriversAndAppsPCR = driversAndAppsPCR GrubChainloaderUsesShimProtocol = grubChainloaderUsesShimProtocol KernelConfigPCR = kernelConfigPCR - PlatformFirmwarePCR = platformFirmwarePCR - SecureBootPolicyPCR = secureBootPolicyPCR ShimFixVariableAuthorityEventsMatchSpec = shimFixVariableAuthorityEventsMatchSpec ShimHasSbatRevocationManagement = shimHasSbatRevocationManagement ShimHasSbatVerification = shimHasSbatVerification @@ -48,7 +45,6 @@ const ( // Export variables and unexported functions for testing var ( ApplySignatureDBUpdate = applySignatureDBUpdate - DefaultEnv = defaultEnv ErrNoHandler = errNoHandler ImageAlwaysMatches = imageAlwaysMatches ImageDigestMatches = imageDigestMatches @@ -69,11 +65,11 @@ var ( NewPcrImagesMeasurer = newPcrImagesMeasurer NewPcrProfileGenerator = newPcrProfileGenerator NewRootPcrBranchCtx = newRootPcrBranchCtx - NewRootVarsCollector = newRootVarsCollector NewSecureBootNamespaceRules = newSecureBootNamespaceRules NewShimImageHandle = newShimImageHandle NewShimLoadHandler = newShimLoadHandler NewShimLoadHandlerConstructor = newShimLoadHandlerConstructor + NewVariableSetCollector = newVariableSetCollector OpenPeImage = openPeImage ParseShimVersion = parseShimVersion ParseShimVersionDataIdent = parseShimVersionDataIdent @@ -100,6 +96,7 @@ type ImageLoadParamsSet = imageLoadParamsSet type ImageRules = imageRules type ImageSectionExists = imageSectionExists type ImageSignedByOrganization = imageSignedByOrganization +type InitialVarReaderKey = initialVarReaderKey type LoadParams = loadParams type NullLoadHandler = nullLoadHandler type PcrBranchContext = pcrBranchContext @@ -107,8 +104,6 @@ type PcrFlags = pcrFlags type PcrImagesMeasurer = pcrImagesMeasurer type PcrProfileContext = pcrProfileContext type PeImageHandle = peImageHandle -type RootVarReaderKey = rootVarReaderKey -type RootVarsCollector = rootVarsCollector type SbatComponent = sbatComponent type SbatComponentExists = sbatComponentExists type SecureBootAuthority = secureBootAuthority @@ -126,6 +121,7 @@ type ShimVersion = shimVersion type SignatureDBUpdateFirmwareQuirk = signatureDBUpdateFirmwareQuirk type UbuntuCoreUKILoadHandler = ubuntuCoreUKILoadHandler type VarBranch = varBranch +type VariableSetCollector = variableSetCollector type VarReadWriter = varReadWriter type VendorAuthorityGetter = vendorAuthorityGetter @@ -146,14 +142,6 @@ func (s *ImageLoadSequences) Params() imageLoadParamsSet { return s.params } -func MockEventLogPath(path string) (restore func()) { - origPath := eventLogPath - eventLogPath = path - return func() { - eventLogPath = origPath - } -} - func MockMakeImageLoadHandlerMap(fn func() imageLoadHandlerMap) (restore func()) { orig := makeImageLoadHandlerMap makeImageLoadHandlerMap = fn @@ -194,14 +182,6 @@ func MockOpenPeImage(fn func(Image) (peImageHandle, error)) (restore func()) { } } -func MockReadVar(fn func(string, efi.GUID) ([]byte, efi.VariableAttributes, error)) (restore func()) { - origReadVar := readVar - readVar = fn - return func() { - readVar = origReadVar - } -} - func MockSnapdenvTesting(testing bool) (restore func()) { orig := snapdenvTesting snapdenvTesting = func() bool { return testing } @@ -210,8 +190,8 @@ func MockSnapdenvTesting(testing bool) (restore func()) { } } -func NewRootVarReader(host HostEnvironment) *rootVarReader { - return &rootVarReader{ +func NewInitialVarReader(host HostEnvironment) *initialVarReader { + return &initialVarReader{ host: host, overrides: make(map[efi.VariableDescriptor]varContents)} } @@ -224,12 +204,13 @@ func NewVarUpdate(prev *varUpdate, name efi.VariableDescriptor, attrs efi.Variab data: data} } -type mockRootVarsModifierOption rootVarsModifier +type mockInitialVariablesModifierOption internal.InitialVariablesModifier -func (o mockRootVarsModifierOption) applyOptionTo(gen *pcrProfileGenerator) { - gen.varModifiers = append(gen.varModifiers, rootVarsModifier(o)) +func (o mockInitialVariablesModifierOption) ApplyOptionTo(visitor internal.PCRProfileOptionVisitor) error { + visitor.AddInitialVariablesModifier(internal.InitialVariablesModifier(o)) + return nil } -func WithMockRootVarsModifierOption(fn func(vars *RootVarsCollector) error) PCRProfileOption { - return mockRootVarsModifierOption(fn) +func WithMockInitialVariablesModifierOption(fn func(internal.VariableSet) error) PCRProfileOption { + return mockInitialVariablesModifierOption(fn) } diff --git a/efi/fw_load_handler.go b/efi/fw_load_handler.go index a43f593d..dcf31ebb 100644 --- a/efi/fw_load_handler.go +++ b/efi/fw_load_handler.go @@ -53,7 +53,7 @@ func (h *fwLoadHandler) measureSeparator(ctx pcrBranchContext, pcr tpm2.Handle, data, ok := event.Data.(*tcglog.SeparatorEventData) if !ok { - // if decoding fails, the resulting type is guaranteed to implement error. + // if the event data failed to decode, the resulting implementation is guaranteed to implement error. return fmt.Errorf("cannot measure invalid separator event: %w", event.Data.(error)) } if data.IsError() { @@ -69,7 +69,7 @@ func (h *fwLoadHandler) readAndMeasureSignatureDb(ctx pcrBranchContext, name efi return nil, xerrors.Errorf("cannot read current variable: %w", err) } - ctx.MeasureVariable(secureBootPolicyPCR, name.GUID, name.Name, db) + ctx.MeasureVariable(internal.SecureBootPolicyPCR, name.GUID, name.Name, db) return db, nil } @@ -91,7 +91,7 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error // This hard-codes a profile that will only work on devices with secure boot enabled, // deployed mode on (where UEFI >= 2.5), without a UEFI debugger enabled and which // measure events in the correct order. - ctx.MeasureVariable(secureBootPolicyPCR, efi.GlobalVariable, sbStateName, []byte{1}) + ctx.MeasureVariable(internal.SecureBootPolicyPCR, efi.GlobalVariable, sbStateName, []byte{1}) if _, err := h.readAndMeasureSignatureDb(ctx, PK); err != nil { return xerrors.Errorf("cannot measure PK: %w", err) } @@ -118,19 +118,19 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error events = events[1:] switch { - case e.PCRIndex < tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: + case e.PCRIndex < tcglog.PCRIndex(internal.SecureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: // pre-OS to OS-present signal foundOsPresent = true - case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: + case e.PCRIndex == tcglog.PCRIndex(internal.SecureBootPolicyPCR) && e.EventType == tcglog.EventTypeSeparator: // end of secure boot configuration signal if foundSecureBootSeparator { return errors.New("unexpected separator") } - if err := h.measureSeparator(ctx, secureBootPolicyPCR, e); err != nil { + if err := h.measureSeparator(ctx, internal.SecureBootPolicyPCR, e); err != nil { return err } foundSecureBootSeparator = true - case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeEFIVariableAuthority: + case e.PCRIndex == tcglog.PCRIndex(internal.SecureBootPolicyPCR) && e.EventType == tcglog.EventTypeEFIVariableAuthority: // secure boot verification event - shouldn't see this before the end of secure // boot configuration signal. if !foundSecureBootSeparator { @@ -138,14 +138,14 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error } digest := tpm2.Digest(e.Digests[ctx.PCRAlg()]) ctx.FwContext().AppendVerificationEvent(digest) - ctx.ExtendPCR(secureBootPolicyPCR, digest) - case e.PCRIndex == tcglog.PCRIndex(secureBootPolicyPCR) && e.EventType == tcglog.EventTypeEFIVariableDriverConfig: + ctx.ExtendPCR(internal.SecureBootPolicyPCR, digest) + case e.PCRIndex == tcglog.PCRIndex(internal.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 == tcglog.PCRIndex(secureBootPolicyPCR): + case e.PCRIndex == tcglog.PCRIndex(internal.SecureBootPolicyPCR): return fmt.Errorf("unexpected event type (%v) found in log", e.EventType) default: // not a secure boot event @@ -166,7 +166,7 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { donePcrReset := false for _, event := range h.log.Events { - if event.PCRIndex != tcglog.PCRIndex(platformFirmwarePCR) { + if event.PCRIndex != tcglog.PCRIndex(internal.PlatformFirmwarePCR) { continue } if event.EventType == tcglog.EventTypeNoAction { @@ -184,14 +184,14 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { } if !donePcrReset { - ctx.ResetPCR(platformFirmwarePCR) + ctx.ResetPCR(internal.PlatformFirmwarePCR) donePcrReset = true } if event.EventType == tcglog.EventTypeSeparator { - return h.measureSeparator(ctx, platformFirmwarePCR, event) + return h.measureSeparator(ctx, internal.PlatformFirmwarePCR, event) } - ctx.ExtendPCR(platformFirmwarePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) + ctx.ExtendPCR(internal.PlatformFirmwarePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) } return errors.New("missing separator") @@ -199,14 +199,14 @@ func (h *fwLoadHandler) measurePlatformFirmware(ctx pcrBranchContext) error { func (h *fwLoadHandler) measureDriversAndApps(ctx pcrBranchContext) error { for _, event := range h.log.Events { - if event.PCRIndex != tcglog.PCRIndex(driversAndAppsPCR) { + if event.PCRIndex != tcglog.PCRIndex(internal.DriversAndAppsPCR) { continue } if event.EventType == tcglog.EventTypeSeparator { - return h.measureSeparator(ctx, driversAndAppsPCR, event) + return h.measureSeparator(ctx, internal.DriversAndAppsPCR, event) } - ctx.ExtendPCR(driversAndAppsPCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) + ctx.ExtendPCR(internal.DriversAndAppsPCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) } return errors.New("missing separator") @@ -252,18 +252,18 @@ func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) error event := events[0] events = events[1:] - if event.PCRIndex != tcglog.PCRIndex(bootManagerCodePCR) { + if event.PCRIndex != tcglog.PCRIndex(internal.BootManagerCodePCR) { continue } if event.EventType == tcglog.EventTypeSeparator { - if err := h.measureSeparator(ctx, bootManagerCodePCR, event); err != nil { + if err := h.measureSeparator(ctx, internal.BootManagerCodePCR, event); err != nil { return err } measuredSeparator = true break } - ctx.ExtendPCR(bootManagerCodePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) + ctx.ExtendPCR(internal.BootManagerCodePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) } if !measuredSeparator { @@ -279,7 +279,7 @@ func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) error event := events[0] events = events[1:] - if event.PCRIndex != tcglog.PCRIndex(bootManagerCodePCR) { + if event.PCRIndex != tcglog.PCRIndex(internal.BootManagerCodePCR) { continue } if event.EventType != tcglog.EventTypeEFIBootServicesApplication { @@ -295,7 +295,7 @@ func (h *fwLoadHandler) measureBootManagerCodePreOS(ctx pcrBranchContext) error } if isAbsolute { // copy the digest to the policy - ctx.ExtendPCR(bootManagerCodePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) + ctx.ExtendPCR(internal.BootManagerCodePCR, tpm2.Digest(event.Digests[ctx.PCRAlg()])) } // If it's not Absolute, we assume it's related to the OS launch which we will predict // later on. If it's something else, discarding it here creates an invalid policy but this is @@ -316,28 +316,28 @@ func (h *fwLoadHandler) MeasureImageStart(ctx pcrBranchContext) error { // 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 { + if pcr == internal.PlatformFirmwarePCR { continue } ctx.ResetPCR(pcr) } - if ctx.PCRs().Contains(platformFirmwarePCR) { + if ctx.PCRs().Contains(internal.PlatformFirmwarePCR) { if err := h.measurePlatformFirmware(ctx); err != nil { return fmt.Errorf("cannot measure platform firmware: %w", err) } } - if ctx.PCRs().Contains(driversAndAppsPCR) { + if ctx.PCRs().Contains(internal.DriversAndAppsPCR) { if err := h.measureDriversAndApps(ctx); err != nil { return fmt.Errorf("cannot measure drivers and apps: %w", err) } } - if ctx.PCRs().Contains(bootManagerCodePCR) { + if ctx.PCRs().Contains(internal.BootManagerCodePCR) { if err := h.measureBootManagerCodePreOS(ctx); err != nil { return fmt.Errorf("cannot measure boot manager code: %w", err) } } - if ctx.PCRs().Contains(secureBootPolicyPCR) { + if ctx.PCRs().Contains(internal.SecureBootPolicyPCR) { if err := h.measureSecureBootPolicyPreOS(ctx); err != nil { return xerrors.Errorf("cannot measure secure boot policy: %w", err) } @@ -390,7 +390,7 @@ func (m *fwImageLoadMeasurer) measureVerification() error { return nil } m.FwContext().AppendVerificationEvent(digest) - m.ExtendPCR(secureBootPolicyPCR, digest) + m.ExtendPCR(internal.SecureBootPolicyPCR, digest) return nil } @@ -399,18 +399,18 @@ func (m *fwImageLoadMeasurer) measurePEImageDigest() error { if err != nil { return xerrors.Errorf("cannot compute PE digest: %w", err) } - m.ExtendPCR(bootManagerCodePCR, digest) + m.ExtendPCR(internal.BootManagerCodePCR, digest) return nil } func (m *fwImageLoadMeasurer) measure() error { - if m.PCRs().Contains(secureBootPolicyPCR) { + if m.PCRs().Contains(internal.SecureBootPolicyPCR) { if err := m.measureVerification(); err != nil { return xerrors.Errorf("cannot measure secure boot event: %w", err) } } - if m.PCRs().Contains(bootManagerCodePCR) { + if m.PCRs().Contains(internal.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 5869e5bb..1eeab096 100644 --- a/efi/fw_load_handler_test.go +++ b/efi/fw_load_handler_test.go @@ -31,6 +31,7 @@ import ( "github.com/canonical/tcglog-parser" . "github.com/snapcore/secboot/efi" + "github.com/snapcore/secboot/efi/internal" "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" ) @@ -54,7 +55,7 @@ type testFwMeasureImageStartData struct { } func (s *fwLoadHandlerSuite) testMeasureImageStart(c *C, data *testFwMeasureImageStartData) *FwContext { - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(data.vars, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(data.vars, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: data.alg, pcrs: data.pcrs}, nil, collector.Next()) @@ -75,7 +76,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfile(c *C) vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -99,7 +100,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileSecureB SecureBootDisabled: true, }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -123,7 +124,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyProfileInclude IncludeDriverLaunch: true, }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 7, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchMeasureVariableEvent, varName: efi.VariableDescriptor{Name: "SecureBoot", GUID: efi.GlobalVariable}, varData: []byte{0x01}}, @@ -144,7 +145,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfile(c *C) { vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, @@ -164,7 +165,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileWithoutC NoCallingEFIApplicationEvent: true, }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, @@ -182,7 +183,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileIncludeS IncludeSysPrepAppLaunch: true, }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4")}, @@ -203,7 +204,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileIncludeA IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, @@ -224,7 +225,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileIncludeA IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x8feeecf1, 0xbcfd, 0x4a78, 0x9231, [...]byte{0x48, 0x01, 0x56, 0x6b, 0x35, 0x67}), }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, @@ -246,7 +247,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartBootManagerCodeProfileIgnoreUn IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0xee993080, 0x5197, 0x4d4e, 0xb63c, [...]byte{0xf1, 0xf7, 0x41, 0x3e, 0x33, 0xce}), }, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba")}, @@ -261,7 +262,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartSecureBootPolicyAndBootManager vars: vars, logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR, SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR, internal.SecureBootPolicyPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchResetEvent}, {pcr: 7, eventType: mockPcrBranchResetEvent}, @@ -281,7 +282,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartPlatformFirmwareProfile(c *C) s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(PlatformFirmwarePCR), + pcrs: MakePcrFlags(internal.PlatformFirmwarePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 0, eventType: mockPcrBranchResetEvent}, {pcr: 0, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6")}, @@ -296,7 +297,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, - pcrs: MakePcrFlags(PlatformFirmwarePCR), + pcrs: MakePcrFlags(internal.PlatformFirmwarePCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 0, eventType: mockPcrBranchResetCRTMPCREvent, locality: 3}, {pcr: 0, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6")}, @@ -311,7 +312,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfile(c *C) { s.testMeasureImageStart(c, &testFwMeasureImageStartData{ logOptions: &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}, alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(DriversAndAppsPCR), + pcrs: MakePcrFlags(internal.DriversAndAppsPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 2, eventType: mockPcrBranchResetEvent}, {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, @@ -323,7 +324,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, - pcrs: MakePcrFlags(DriversAndAppsPCR), + pcrs: MakePcrFlags(internal.DriversAndAppsPCR), expectedEvents: []*mockPcrBranchEvent{ {pcr: 2, eventType: mockPcrBranchResetEvent}, {pcr: 2, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6")}, @@ -334,10 +335,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartDriversAndAppsProfile2(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_1(c *C) { // Insert a second EV_SEPARATOR event into PCR7 - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -358,10 +359,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_1(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_2(c *C) { // Prepend a verification event into PCR7 before the EV_SEPARATOR - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -385,10 +386,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_2(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_3(c *C) { // Append a configuration event into PCR7 after the EV_SEPARATOR - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -412,10 +413,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_3(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_4(c *C) { // Insert an unexpected event type into PCR7 - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -439,10 +440,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR7_4(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR0_1(c *C) { // Insert an invalid StartupLocality event data into the log - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(PlatformFirmwarePCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.PlatformFirmwarePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -464,10 +465,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR0_1(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR0_2(c *C) { // Insert an extra StartupLocality event data into the log - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(PlatformFirmwarePCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.PlatformFirmwarePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -493,10 +494,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR0_2(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR4_1(c *C) { // Insert an unexpected event type in the OS-present phase - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.BootManagerCodePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -514,10 +515,10 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR4_1(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR4_2(c *C) { // Insert invalid event data in the OS-present phase so that internal.IsAbsoluteAgentLaunch returns an error - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR)}, nil, collector.Next()) + pcrs: MakePcrFlags(internal.BootManagerCodePCR)}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{ Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, @@ -538,7 +539,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogPCR4_2(c *C) { func (s *fwLoadHandlerSuite) testMeasureImageStartErrBadLogSeparatorError(c *C, pcr tpm2.Handle) error { // Insert an invalid error separator event into the log for the specified pcr - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, pcrs: MakePcrFlags(pcr)}, nil, collector.Next()) @@ -579,7 +580,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogSeparatorErrorPCR7(c func (s *fwLoadHandlerSuite) testMeasureImageStartErrBadLogInvalidSeparator(c *C, pcr tpm2.Handle) error { // Insert an invalid separator event into the log for the specified PCR - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, pcrs: MakePcrFlags(pcr)}, nil, collector.Next()) @@ -620,7 +621,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLogInvalidSeparatorPCR7( func (s *fwLoadHandlerSuite) testMeasureImageStartErrBadLogMissingSeparator(c *C, pcr tpm2.Handle) error { // Remove the separator from the specified PCR - collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(nil, nil)) + collector := NewVariableSetCollector(efitest.NewMockHostEnvironment(nil, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, pcrs: MakePcrFlags(pcr)}, nil, collector.Next()) @@ -703,7 +704,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfile(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), db: msDb(c), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), expectedEvents: []*mockPcrBranchEvent{ @@ -721,7 +722,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileExisting s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), db: msDb(c), fc: fc, image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), @@ -731,7 +732,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyProfileExisting func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "bf6b6dfdb1f6435a81e4808db7f846d86d170566e4753d4384fdab6504be4fb9")}, @@ -742,7 +743,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile1(c *C) { func (s *fwLoadHandlerSuite) TestMeasureImageLoadBootManagerCodeProfile2(c *C) { s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR), image: newMockImage().appendSignatures(efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig3)), expectedEvents: []*mockPcrBranchEvent{ {pcr: 4, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "dbffd70a2c43fd2c1931f18b8f8c08c5181db15f996f747dfed34def52fad036")}, @@ -755,7 +756,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageLoadSecureBootPolicyAndBootManagerC s.testMeasureImageLoad(c, &testFwMeasureImageLoadData{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(BootManagerCodePCR, SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.BootManagerCodePCR, internal.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 5af1f4fc..a90d73ff 100644 --- a/efi/grub_load_handler_test.go +++ b/efi/grub_load_handler_test.go @@ -25,6 +25,7 @@ import ( efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" . "github.com/snapcore/secboot/efi" + "github.com/snapcore/secboot/efi/internal" "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" ) @@ -42,7 +43,7 @@ var _ = Suite(&grubLoadHandlerSuite{}) func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_7(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -71,7 +72,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_7(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_6(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -100,7 +101,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_6(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShim(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ @@ -129,7 +130,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShim(c *C) { func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShimError(c *C) { ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - pcrs: MakePcrFlags(SecureBootPolicyPCR), + pcrs: MakePcrFlags(internal.SecureBootPolicyPCR), handlers: s, }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ diff --git a/efi/image_rules_defs.go b/efi/image_rules_defs.go index 77845088..69c95baf 100644 --- a/efi/image_rules_defs.go +++ b/efi/image_rules_defs.go @@ -22,58 +22,25 @@ package efi import ( "crypto" "crypto/x509" + + "github.com/snapcore/secboot/efi/internal" ) func makeMicrosoftUEFICASecureBootNamespaceRules() *secureBootNamespaceRules { return newSecureBootNamespaceRules( "Microsoft UEFI CA", withAuthority( - // CN=Microsoft Corporation UEFI CA 2011,O=Microsoft Corporation,L=Redmond,ST=Washington,C=US - []byte{ - 0x30, 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, - 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, - 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, - 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2b, 0x30, - 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4d, 0x69, - 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, - 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x55, 0x45, 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, - 0x31, 0x31, - }, - // SKID - []byte{ - 0x13, 0xad, 0xbf, 0x43, 0x09, 0xbd, 0x82, 0x70, 0x9c, 0x8c, - 0xd5, 0x4f, 0x31, 0x6e, 0xd5, 0x22, 0x98, 0x8a, 0x1b, 0xd4, - }, - // pubkey alg - x509.RSA, + internal.MSUefiCA2011.Subject, + internal.MSUefiCA2011.SubjectKeyId, + internal.MSUefiCA2011.PublicKeyAlgorithm, ), // TODO(chrisccoulson): add tests for this when we find something that it's // been used to sign and we have a signing certificate in the wild that we // can add to embeds_test.go in order to create a mock shim with it withAuthority( - // CN=Microsoft UEFI CA 2023,O=Microsoft Corporation,C=US - []byte{ - 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, - 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, - 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x1f, 0x30, - 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x4d, 0x69, - 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x55, 0x45, - 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x33, - }, - []byte{ - 0x81, 0xaa, 0x6b, 0x32, 0x44, 0xc9, 0x35, 0xbc, 0xe0, 0xd6, - 0x62, 0x8a, 0xf3, 0x98, 0x27, 0x42, 0x1e, 0x32, 0x49, 0x7d, - }, - // pubkey alg - x509.RSA, + internal.MSUefiCA2023.Subject, + internal.MSUefiCA2023.SubjectKeyId, + internal.MSUefiCA2023.PublicKeyAlgorithm, ), withSelfSignedSignerOnlyForTesting( // O = Snake Oil diff --git a/efi/internal/MicrosoftKEK.crt b/efi/internal/MicrosoftKEK.crt new file mode 100644 index 00000000..37c814a7 --- /dev/null +++ b/efi/internal/MicrosoftKEK.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF6DCCA9CgAwIBAgIKYQrRiAAAAAAAAzANBgkqhkiG9w0BAQsFADCBkTELMAkG +A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE7MDkGA1UEAxMyTWljcm9z +b2Z0IENvcnBvcmF0aW9uIFRoaXJkIFBhcnR5IE1hcmtldHBsYWNlIFJvb3QwHhcN +MTEwNjI0MjA0MTI5WhcNMjYwNjI0MjA1MTI5WjCBgDELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p +Y3Jvc29mdCBDb3Jwb3JhdGlvbjEqMCgGA1UEAxMhTWljcm9zb2Z0IENvcnBvcmF0 +aW9uIEtFSyBDQSAyMDExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +xOi1ir+tVyawJsPq5/tXekQCXQcN2krldCrmsA/sbevsf7njWmMyfBEXTw7jC6c4 +FZOOxvXghLGamyzn9beR1gnh4sAEqKwwHN9I8wZQmmSnUX/IhU+PIIbO/i/hn/+C +wO3pzc70U2piOgtDueIl/f4F+dTEFKsR4iOJjXC3pB1N7K7lnPoWwtfBy9ToxC/l +me4kiwPsjfKL6sNK+0MREgt+tUeSbNzmBInr9TME6xABKnHl+YMTPP8lCS9odkb/ +uk++3K1xKliq+w7SeT3km2U7zCkqn/xyWaLrrpLv9jUTgMYC7ORfzJ12ze9jksGv +eUCEeYd/41Ko6J17B2mPFQIDAQABo4IBTzCCAUswEAYJKwYBBAGCNxUBBAMCAQAw +HQYDVR0OBBYEFGL8Q82gPqTLZxLSW9lVrHvMtopfMBkGCSsGAQQBgjcUAgQMHgoA +UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY +MBaAFEVmUkPhflgRv9ZOniNVCDs6ImqoMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6 +Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY0NvclRoaVBh +ck1hclJvb18yMDEwLTEwLTA1LmNybDBgBggrBgEFBQcBAQRUMFIwUAYIKwYBBQUH +MAKGRGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljQ29yVGhp +UGFyTWFyUm9vXzIwMTAtMTAtMDUuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQDUhIj1 +FJQYAsoqPPsqkhwM16DR8ehSZqjuorV1epAAqi2kdlrqebe5N2pRexBk9uFk8gJn +vveoG3i9us6IWGQM1lfIGaNfBdbbxtBpzkhLMrfrXdIw9cD1uLp4B6Mr/pvbNFaE +7ILKrkElcJxr6f6QD9eWH+XnlB+yKgyNS/8oKRB799d8pdF2uQXIee0PkJKcwv7f +b35sD3vUwUXdNFGWOQ/lXlbYGAWW9AemQrOgd/0IGfJxVsyfhiOkh8um/Vh+1Gln +FZF+gfJ/E+UNi4o8h4Tr4869Q+WtLYSTjmorWnxE+lKqgcgtHLvgUt8AEfiaPcFg +sOEztaOI0WUZChrnrHykwYKHTjixLw3FFIdv/Y0uvDm25+bD4OTNJ4TvlELvKYuQ +RkE7gRtn2PlDWWXLDbz9AJJP9HU7p6kk/FBBQHngLU8Kaid2blLtlml7rw/3hwXQ +RcKtUxSBH/swBKo3NmHaSmkbNNho7dYCz2yUDNPPbCJ5rbHwvAOiRmCpxAfCIYLx +/fLoeTJgv9ispSIUS8rB2EvrfT9XNbLmT3W0sGADIlOukXkd1ptBHxWGVHCy3g01 +D3ywNHK6l2A78HnrorIcXaIWuIfF6Rv2tZclbzif45H6inmYw2kOt6McIAWX+MoU +rgDXxPPAFBB1azSgG7WZYPNcsMVXTjbSMoS/ng== +-----END CERTIFICATE----- diff --git a/efi/default_env.go b/efi/internal/default_env.go similarity index 90% rename from efi/default_env.go rename to efi/internal/default_env.go index 692a283f..e792cfde 100644 --- a/efi/default_env.go +++ b/efi/internal/default_env.go @@ -17,7 +17,7 @@ * */ -package efi +package internal import ( "os" @@ -47,4 +47,6 @@ func (e defaultEnvImpl) ReadEventLog() (*tcglog.Log, error) { return tcglog.ReadLog(f, &tcglog.LogOptions{}) } -var defaultEnv = defaultEnvImpl{} +// DefaultEnv corresponds to the environment associated with the host +// machine. +var DefaultEnv = defaultEnvImpl{} diff --git a/efi/default_env_test.go b/efi/internal/default_env_test.go similarity index 80% rename from efi/default_env_test.go rename to efi/internal/default_env_test.go index 777a1a9b..0fbc2215 100644 --- a/efi/default_env_test.go +++ b/efi/internal/default_env_test.go @@ -17,9 +17,10 @@ * */ -package efi_test +package internal_test import ( + _ "embed" "io" "os" "path/filepath" @@ -27,12 +28,24 @@ import ( efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" "github.com/canonical/tcglog-parser" - . "github.com/snapcore/secboot/efi" + . "github.com/snapcore/secboot/efi/internal" "github.com/snapcore/secboot/internal/efitest" + "github.com/snapcore/secboot/internal/testutil" . "gopkg.in/check.v1" ) +var ( + //go:embed MicrosoftKEK.crt + msKEKCertPEM []byte + + msKEKCert []byte +) + +func init() { + msKEKCert = testutil.MustDecodePEMType("CERTIFICATE", msKEKCertPEM) +} + type defaultEnvSuite struct{} var _ = Suite(&defaultEnvSuite{}) @@ -43,7 +56,22 @@ type testReadVarData struct { } func (s *defaultEnvSuite) testReadVar(c *C, data *testReadVarData) { - vars := makeMockVars(c, withMsSecureBootConfig()) + ownerGuid := efi.MakeGUID(0x77fa9abd, 0x0359, 0x4d32, 0xbd60, [...]uint8{0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b}) + kek := &efi.SignatureList{ + Type: efi.CertX509Guid, + Signatures: []*efi.SignatureData{ + { + Owner: ownerGuid, + Data: msKEKCert, + }, + }, + } + dbx := efitest.NewSignatureListNullSHA256(ownerGuid) + vars := efitest.MakeMockVars() + vars.SetSecureBoot(true) + vars.SetKEK(c, efi.SignatureDatabase{kek}) + vars.SetDbx(c, efi.SignatureDatabase{dbx}) + restore := MockReadVar(func(name string, guid efi.GUID) ([]byte, efi.VariableAttributes, error) { entry, exists := vars[efi.VariableDescriptor{Name: name, GUID: guid}] if !exists { @@ -73,7 +101,7 @@ func (s *defaultEnvSuite) TestReadVar1(c *C) { func (s *defaultEnvSuite) TestReadVar2(c *C) { s.testReadVar(c, &testReadVarData{ - name: "PK", + name: "KEK", guid: efi.GlobalVariable}) } diff --git a/efi/internal/export_test.go b/efi/internal/export_test.go new file mode 100644 index 00000000..f2191a36 --- /dev/null +++ b/efi/internal/export_test.go @@ -0,0 +1,38 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2019-2024 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package internal + +import efi "github.com/canonical/go-efilib" + +func MockEventLogPath(path string) (restore func()) { + origPath := eventLogPath + eventLogPath = path + return func() { + eventLogPath = origPath + } +} + +func MockReadVar(fn func(string, efi.GUID) ([]byte, efi.VariableAttributes, error)) (restore func()) { + origReadVar := readVar + readVar = fn + return func() { + readVar = origReadVar + } +} diff --git a/efi/internal/known_secureboot_cas.go b/efi/internal/known_secureboot_cas.go new file mode 100644 index 00000000..a3a77587 --- /dev/null +++ b/efi/internal/known_secureboot_cas.go @@ -0,0 +1,83 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2024 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package internal + +import "crypto/x509" + +// SecureBootAuthorityIdentity corresponds to the identify of a secure boot +// authority. +type SecureBootAuthorityIdentity struct { + Subject []byte + SubjectKeyId []byte + PublicKeyAlgorithm x509.PublicKeyAlgorithm + + Issuer []byte + AuthorityKeyId []byte + SignatureAlgorithm x509.SignatureAlgorithm +} + +var ( + // MSUefiCA2011 corresponds to the 2011 Microsoft UEFI CA + MSUefiCA2011 = &SecureBootAuthorityIdentity{ + // CN=Microsoft Corporation UEFI CA 2011,O=Microsoft Corporation,L=Redmond,ST=Washington,C=US + Subject: []byte{ + 0x30, 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, + 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x2b, 0x30, + 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, + 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x55, 0x45, 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x31, 0x31, + }, + SubjectKeyId: []byte{ + 0x13, 0xad, 0xbf, 0x43, 0x09, 0xbd, 0x82, 0x70, 0x9c, 0x8c, + 0xd5, 0x4f, 0x31, 0x6e, 0xd5, 0x22, 0x98, 0x8a, 0x1b, 0xd4, + }, + PublicKeyAlgorithm: x509.RSA, + } + + // MSUefiCA2023 corresponds to the 2023 Microsoft UEFI CA, which will eventually + // replace the 2011 CA. + MSUefiCA2023 = &SecureBootAuthorityIdentity{ + // CN=Microsoft UEFI CA 2023,O=Microsoft Corporation,C=US + Subject: []byte{ + 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, + 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x4d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x55, 0x45, + 0x46, 0x49, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x33, + }, + SubjectKeyId: []byte{ + 0x81, 0xaa, 0x6b, 0x32, 0x44, 0xc9, 0x35, 0xbc, 0xe0, 0xd6, + 0x62, 0x8a, 0xf3, 0x98, 0x27, 0x42, 0x1e, 0x32, 0x49, 0x7d, + }, + PublicKeyAlgorithm: x509.RSA, + } +) diff --git a/efi/internal/options.go b/efi/internal/options.go new file mode 100644 index 00000000..3402dac4 --- /dev/null +++ b/efi/internal/options.go @@ -0,0 +1,67 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2024 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package internal + +import ( + efi "github.com/canonical/go-efilib" + "github.com/canonical/go-tpm2" + "github.com/canonical/tcglog-parser" +) + +type InitialVariablesModifier func(VariableSet) error + +type PCRProfileOptionVisitor interface { + // AddPCRs adds the supplied PCRs to the profile. + AddPCRs(pcrs ...tpm2.Handle) + + // SetEnvironment overrides the host environment to the supplied environment. + SetEnvironment(env HostEnvironment) + + // AddInitialVariablesModifier adds a function that will be called to allow + // the initial variable set for profile generation to be modified. + AddInitialVariablesModifier(fn InitialVariablesModifier) +} + +// HostEnvironment is an interface that abstracts out an EFI environment, so that +// consumers of the API can provide a custom mechanism to read EFI variables or parse +// the TCG event log. This needs to be kept in sync with [efi.HostEnvironment]. +type HostEnvironment interface { + // ReadVar reads the specified EFI variable + ReadVar(name string, guid efi.GUID) ([]byte, efi.VariableAttributes, error) + + // ReadEventLog reads the TCG event log + ReadEventLog() (*tcglog.Log, error) +} + +// VariableSet corresponds to a set of EFI variables. +type VariableSet interface { + // ReadVar reads the specified EFI variable for this set. + ReadVar(name string, guid efi.GUID) ([]byte, efi.VariableAttributes, error) + + // WriteVar updates the specified EFI variable for this set, for + // boot components that update variables. Each individual write + // creates a new intitial set of variables for which a profile will be + // generated against to accommodate interrupted sequences of writes. + WriteVar(name string, guid efi.GUID, attrs efi.VariableAttributes, data []byte) error + + // Clone creates a copy of this variable set to make it possible to create + // branches by setting variables to different values in each returned set. + Clone() VariableSet +} diff --git a/efi/internal/tcg_pcrs.go b/efi/internal/tcg_pcrs.go new file mode 100644 index 00000000..16e786f6 --- /dev/null +++ b/efi/internal/tcg_pcrs.go @@ -0,0 +1,39 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2019 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package internal + +import "github.com/canonical/go-tpm2" + +const ( + // PlatformFirmarePCR is the SRTM, POST BIOS, and Embedded Drivers PCR + PlatformFirmwarePCR tpm2.Handle = 0 + + // HostPlatformConfigPCR is the Host Platform Configuration PCR + HostPlatformConfigPCR tpm2.Handle = 1 + + // DriversAndAppsPCR is the UEFI Drivers and UEFI Applications PCR + DriversAndAppsPCR tpm2.Handle = 2 + + // BootManagerCodePCR is the Boot Manager Code and Boot Attempts PCR + BootManagerCodePCR tpm2.Handle = 4 + + // SecureBootPolicyPCR is the Secure Boot Policy Measurements PCR + SecureBootPolicyPCR tpm2.Handle = 7 +) diff --git a/efi/pcr_branch_context.go b/efi/pcr_branch_context.go index c993efec..24697241 100644 --- a/efi/pcr_branch_context.go +++ b/efi/pcr_branch_context.go @@ -24,6 +24,7 @@ import ( "github.com/canonical/go-tpm2" "github.com/canonical/tcglog-parser" + "github.com/snapcore/secboot/efi/internal" secboot_tpm2 "github.com/snapcore/secboot/tpm2" ) @@ -97,7 +98,7 @@ func (c *pcrBranchCtx) ResetPCR(pcr tpm2.Handle) { func (c *pcrBranchCtx) ResetCRTMPCR(locality uint8) { value := make([]byte, c.PCRAlg().Size()) value[len(value)-1] = locality - c.branch.AddPCRValue(c.PCRAlg(), int(platformFirmwarePCR), value) + c.branch.AddPCRValue(c.PCRAlg(), int(internal.PlatformFirmwarePCR), value) } func (c *pcrBranchCtx) ExtendPCR(pcr tpm2.Handle, digest tpm2.Digest) { diff --git a/efi/pcr_branch_context_test.go b/efi/pcr_branch_context_test.go index 8913cb4c..71eb824e 100644 --- a/efi/pcr_branch_context_test.go +++ b/efi/pcr_branch_context_test.go @@ -76,7 +76,7 @@ func (s *pcrBranchContextSuite) TestPcrBranchCtxParamsSubBranch(c *C) { } func (s *pcrBranchContextSuite) TestPcrBranchCtxVars(c *C) { - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: efi.GlobalVariable}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil)).Next() bc := NewRootPcrBranchCtx(&mockPcrProfileContext{alg: tpm2.HashAlgorithmSHA256}, nil, new(LoadParams), vars) @@ -96,7 +96,7 @@ func (s *pcrBranchContextSuite) TestPcrBranchCtxVars(c *C) { } func (s *pcrBranchContextSuite) TestPcrBranchCtxVarsSubBranch(c *C) { - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: efi.GlobalVariable}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil)).Next() bc := NewRootPcrBranchCtx(&mockPcrProfileContext{alg: tpm2.HashAlgorithmSHA256}, secboot_tpm2.NewPCRProtectionProfile().RootBranch(), new(LoadParams), vars) diff --git a/efi/pcr_images_measurer_test.go b/efi/pcr_images_measurer_test.go index f4bafe75..26de687a 100644 --- a/efi/pcr_images_measurer_test.go +++ b/efi/pcr_images_measurer_test.go @@ -45,7 +45,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureOneLeaf(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -94,7 +94,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerTwoLeaf(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -146,7 +146,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerNonLeaf(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -203,7 +203,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerTwoNonLeaf(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo1") @@ -279,7 +279,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureWithParams(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -341,7 +341,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureWithInheritedParams profile := secboot_tpm2.NewPCRProtectionProfile() params := &LoadParams{SnapModel: model} - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -395,7 +395,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureWithVars(c *C) { profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil)).Next() @@ -447,7 +447,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureEnsureVarsAreCopied profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{ {Name: "foo", GUID: testGuid1}: {Payload: []byte{1}, Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess}, }, nil)).Next() @@ -504,7 +504,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureWithFwContext(c *C) profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -555,7 +555,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureEnsureFwContextIsCo profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -612,7 +612,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureWithShimContext(c * profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") @@ -663,7 +663,7 @@ func (s *pcrImagesMeasurerSuite) TestPcrImagesMeasurerMeasureEnsureShimContextIs profile := secboot_tpm2.NewPCRProtectionProfile() params := new(LoadParams) - vars := NewRootVarsCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() + vars := NewVariableSetCollector(efitest.NewMockHostEnvironment(efitest.MockVars{}, nil)).Next() h := crypto.SHA256.New() io.WriteString(h, "foo") diff --git a/efi/pcr_profile.go b/efi/pcr_profile.go index 8057245a..f24b6cbf 100644 --- a/efi/pcr_profile.go +++ b/efi/pcr_profile.go @@ -21,43 +21,46 @@ package efi import ( "errors" + "fmt" "github.com/canonical/go-tpm2" "github.com/canonical/tcglog-parser" + "github.com/snapcore/secboot/efi/internal" secboot_tpm2 "github.com/snapcore/secboot/tpm2" "golang.org/x/xerrors" ) // PCRProfileOption is an option for AddPCRProfile type PCRProfileOption interface { - applyOptionTo(gen *pcrProfileGenerator) + ApplyOptionTo(visitor internal.PCRProfileOptionVisitor) error } // PCRProfileEnablePCRsOption is an option for AddPCRProfile that adds one or more PCRs. type PCRProfileEnablePCRsOption interface { PCRProfileOption - PCRs() tpm2.HandleList + PCRs() (tpm2.HandleList, error) } -type pcrProfileSetPcrsOption struct { +type pcrProfileSetPcrOption struct { PCRProfileOption - pcrs pcrFlags + pcr tpm2.Handle } -func newPcrProfileSetPcrsOption(pcrs pcrFlags) *pcrProfileSetPcrsOption { - out := &pcrProfileSetPcrsOption{ - pcrs: pcrs, +func newPcrProfileSetPcrOption(pcr tpm2.Handle) *pcrProfileSetPcrOption { + out := &pcrProfileSetPcrOption{ + pcr: pcr, } out.PCRProfileOption = out return out } -func (o *pcrProfileSetPcrsOption) applyOptionTo(gen *pcrProfileGenerator) { - gen.pcrs |= o.pcrs +func (o *pcrProfileSetPcrOption) ApplyOptionTo(visitor internal.PCRProfileOptionVisitor) error { + visitor.AddPCRs(o.pcr) + return nil } -func (o *pcrProfileSetPcrsOption) PCRs() tpm2.HandleList { - return o.pcrs.PCRs() +func (o *pcrProfileSetPcrOption) PCRs() (tpm2.HandleList, error) { + return tpm2.HandleList{o.pcr}, nil } // WithPlatformFirmwareProfile adds the SRTM, POST BIOS and Embedded Drivers @@ -68,14 +71,14 @@ func (o *pcrProfileSetPcrsOption) PCRs() tpm2.HandleList { // hardware root of trust as opposed to being verified as authentic and prevented // from running otherwise. func WithPlatformFirmwareProfile() PCRProfileEnablePCRsOption { - return newPcrProfileSetPcrsOption(makePcrFlags(platformFirmwarePCR)) + return newPcrProfileSetPcrOption(internal.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() PCRProfileEnablePCRsOption { - return newPcrProfileSetPcrsOption(makePcrFlags(driversAndAppsPCR)) + return newPcrProfileSetPcrOption(internal.DriversAndAppsPCR) } // WithSecureBootPolicyProfile requests that the UEFI secure boot policy profile is @@ -135,7 +138,7 @@ func WithDriversAndAppsProfile() PCRProfileEnablePCRsOption { // of these makes a policy inherently fragile because it is not possible to pre-generate // policy to accomodate updates of these components. func WithSecureBootPolicyProfile() PCRProfileEnablePCRsOption { - return newPcrProfileSetPcrsOption(makePcrFlags(secureBootPolicyPCR)) + return newPcrProfileSetPcrOption(internal.SecureBootPolicyPCR) } // WithBootManagerCodeProfile requests that the UEFI boot manager code and boot attempts @@ -171,7 +174,7 @@ func WithSecureBootPolicyProfile() PCRProfileEnablePCRsOption { // fail before performing a successful attempt, even if the images associated with the // successful attempt are included in this policy. func WithBootManagerCodeProfile() PCRProfileEnablePCRsOption { - return newPcrProfileSetPcrsOption(makePcrFlags(bootManagerCodePCR)) + return newPcrProfileSetPcrOption(internal.BootManagerCodePCR) } // WithKernelConfigProfile adds the kernel config profile. This binds a policy to a @@ -182,7 +185,7 @@ func WithBootManagerCodeProfile() PCRProfileEnablePCRsOption { // 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() PCRProfileEnablePCRsOption { - return newPcrProfileSetPcrsOption(makePcrFlags(kernelConfigPCR)) + return newPcrProfileSetPcrOption(kernelConfigPCR) } // AddPCRProfile adds a profile defined by the supplied options to the supplied @@ -190,7 +193,10 @@ func WithKernelConfigProfile() PCRProfileEnablePCRsOption { // for the PCR digest. The generated profile is defined by the supplied load // sequences and options. func AddPCRProfile(pcrAlg tpm2.HashAlgorithmId, branch *secboot_tpm2.PCRProtectionProfileBranch, loadSequences *ImageLoadSequences, options ...PCRProfileOption) error { - gen := newPcrProfileGenerator(pcrAlg, loadSequences, options...) + gen, err := newPcrProfileGenerator(pcrAlg, loadSequences, options...) + if err != nil { + return err + } if gen.pcrs == 0 { return errors.New("must specify a profile to add") @@ -224,23 +230,25 @@ type pcrProfileGenerator struct { // of every possible EFI variable starting state, and is used for generating // profiles that incorporate signature database updates and changest to // SbatPolicy. - varModifiers []rootVarsModifier + varModifiers []internal.InitialVariablesModifier // log is the host TCG log, which is read from the associated env. log *tcglog.Log } -func newPcrProfileGenerator(pcrAlg tpm2.HashAlgorithmId, loadSequences *ImageLoadSequences, options ...PCRProfileOption) *pcrProfileGenerator { +func newPcrProfileGenerator(pcrAlg tpm2.HashAlgorithmId, loadSequences *ImageLoadSequences, options ...PCRProfileOption) (*pcrProfileGenerator, error) { gen := &pcrProfileGenerator{ pcrAlg: pcrAlg, loadSequences: loadSequences, - env: defaultEnv, + env: internal.DefaultEnv, handlers: makeImageLoadHandlerMap(), } for _, opt := range options { - opt.applyOptionTo(gen) + if err := opt.ApplyOptionTo(gen); err != nil { + return nil, err + } } - return gen + return gen, nil } func (g *pcrProfileGenerator) addPCRProfile(branch *secboot_tpm2.PCRProtectionProfileBranch) error { @@ -255,12 +263,14 @@ func (g *pcrProfileGenerator) addPCRProfile(branch *secboot_tpm2.PCRProtectionPr // Collect all of the starting EFI variable states that we need to // generate branches for. - collector := newRootVarsCollector(g.env) + collector := newVariableSetCollector(g.env) // Collect the starting EFI variable states from the supplied options for i, mod := range g.varModifiers { - if err := mod(collector); err != nil { - return xerrors.Errorf("cannot process host variable modifier %d: %w", i, err) + for j, branch := range collector.PeekAll() { + if err := mod(branch); err != nil { + return fmt.Errorf("cannot process host variable modifier %d for initial branch %d: %w", i, j, err) + } } } @@ -311,6 +321,20 @@ func (g *pcrProfileGenerator) addOnePCRProfileBranch(bp *secboot_tpm2.PCRProtect return nil } +// AddPCRs implements [internal.PCRProfileOptionVisitor.AddPCRs] +func (g *pcrProfileGenerator) AddPCRs(pcrs ...tpm2.Handle) { + g.pcrs |= makePcrFlags(pcrs...) +} + +// SetEnvironment implements [internal.PCRProfileOptionVisitor.SetEnvironment] +func (g *pcrProfileGenerator) SetEnvironment(env internal.HostEnvironment) { + g.env = env +} + +func (g *pcrProfileGenerator) AddInitialVariablesModifier(fn internal.InitialVariablesModifier) { + g.varModifiers = append(g.varModifiers, fn) +} + // PCRAlg implements pcrProfileContext.PCRAlg. func (g *pcrProfileGenerator) PCRAlg() tpm2.HashAlgorithmId { return g.pcrAlg diff --git a/efi/pcr_profile_test.go b/efi/pcr_profile_test.go index 9ec6f5e2..b2f578ac 100644 --- a/efi/pcr_profile_test.go +++ b/efi/pcr_profile_test.go @@ -34,6 +34,7 @@ import ( . "gopkg.in/check.v1" . "github.com/snapcore/secboot/efi" + "github.com/snapcore/secboot/efi/internal" "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" "github.com/snapcore/secboot/internal/tpm2test" @@ -75,27 +76,27 @@ func (s *pcrProfileMockedSuite) TearDownSuite(c *C) { var _ = Suite(&pcrProfileMockedSuite{}) func (s *pcrProfileMockedSuite) TestPcrProfileGeneratorPCRAlg(c *C) { - gen := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA256, NewImageLoadSequences()) + gen, _ := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA256, NewImageLoadSequences()) c.Check(gen.PCRAlg(), Equals, tpm2.HashAlgorithmSHA256) } func (s *pcrProfileMockedSuite) TestPcrProfileGeneratorPCRAlgSHA1(c *C) { - gen := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA1, NewImageLoadSequences()) + gen, _ := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA1, NewImageLoadSequences()) c.Check(gen.PCRAlg(), Equals, tpm2.HashAlgorithmSHA1) } func (s *pcrProfileMockedSuite) TestWithSecureBootPolicyProfile(c *C) { - gen := NewPcrProfileGenerator(tpm2.HashAlgorithmSHA256, NewImageLoadSequences(), WithSecureBootPolicyProfile()) - c.Check(gen.PCRs(), Equals, PcrFlags(1<