diff --git a/efi/fw_load_handler.go b/efi/fw_load_handler.go index 3cef06c5..4af4eb6c 100644 --- a/efi/fw_load_handler.go +++ b/efi/fw_load_handler.go @@ -208,6 +208,19 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error // permitted with the WithSecureBootUserMode option and they are being included in this // branch. includeUserMode := boolParamOrFalse(ctx.Params(), includeSecureBootUserModeParamKey) + autoIncludeUserMode := boolParamOrFalse(ctx.Params(), autoIncludeSecureBootUserModeParamKey) + if autoIncludeUserMode { + for _, e := range h.log.Events { + switch { + case e.PCRIndex == internal_efi.SecureBootPolicyPCR && e.EventType == tcglog.EventTypeEFIVariableDriverConfig: + if data, ok := e.Data.(*tcglog.EFIVariableData); ok { + if data.VariableName == efi.GlobalVariable && data.UnicodeName == "AuditMode" { + includeUserMode = true + } + } + } + } + } switch deployedMode, _, err := ctx.Vars().ReadVar("DeployedMode", efi.GlobalVariable); { case errors.Is(err, efi.ErrVarNotExist): // pre-2.5 UEFI system diff --git a/efi/pcr_profile_test.go b/efi/pcr_profile_test.go index b6848f28..c488e5c9 100644 --- a/efi/pcr_profile_test.go +++ b/efi/pcr_profile_test.go @@ -1270,7 +1270,7 @@ func (s *pcrProfileSuite) TestAddPCRProfileLoadFailsFromLeafImage(c *C) { ), ), }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) - c.Check(err, ErrorMatches, `cannot measure image 0x[[:xdigit:]]{10}: cannot measure image load: kernel is a leaf image`) + c.Check(err, ErrorMatches, `cannot measure image 0x[[:xdigit:]]*: cannot measure image load: kernel is a leaf image`) } func (s *pcrProfileSuite) TestAddPCRProfileUC20WithDbxUpdateWithAllowInsufficientDMAProtection(c *C) { @@ -1441,3 +1441,120 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20WithAllowSecureBootUserMode(c *C) }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile(), WithAllowSecureBootUserMode()) c.Check(err, IsNil) } + +func (s *pcrProfileSuite) TestAddPCRProfileUC20WithAutoAllowSecureBootUserModeWithMeasurements(c *C) { + shim := newMockUbuntuShimImage15_7(c) + grub := newMockUbuntuGrubImage3(c) + recoverKernel := newMockUbuntuKernelImage2(c) + runKernel := newMockUbuntuKernelImage3(c) + + err := s.testAddPCRProfile(c, &testAddPCRProfileData{ + vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2022052400\ngrub,2\n")), withDeployedModeDisabled()), + log: efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, + DisableDeployedMode: true, + }), + alg: tpm2.HashAlgorithmSHA256, + loadSequences: NewImageLoadSequences( + SnapModelParams(testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ + "authority-id": "fake-brand", + "series": "16", + "brand-id": "fake-brand", + "model": "fake-model", + "grade": "secured", + }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")), + ).Append( + NewImageLoadActivity(shim).Loads( + NewImageLoadActivity(grub, KernelCommandlineParams("console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=recover")).Loads( + NewImageLoadActivity(grub, KernelCommandlineParams("console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run")).Loads( + NewImageLoadActivity(runKernel), + ), + NewImageLoadActivity(recoverKernel), + ), + ), + ), + expected: []tpm2.PCRValues{ + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), + }, + }, + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), + }, + }, + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "d6a99cb0ea5ac9290b65b8847bb48613fc504a798229fb37e88b7b33337f4c60"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), + }, + }, + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "d6a99cb0ea5ac9290b65b8847bb48613fc504a798229fb37e88b7b33337f4c60"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), + }, + }, + }, + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile(), WithAutoAllowSecureBootUserMode()) + c.Check(err, IsNil) +} + +func (s *pcrProfileSuite) TestAddPCRProfileUC20WithAutoAllowSecureBootUserModeNoMeasurements(c *C) { + shim := newMockUbuntuShimImage15_7(c) + grub := newMockUbuntuGrubImage3(c) + recoverKernel := newMockUbuntuKernelImage2(c) + runKernel := newMockUbuntuKernelImage3(c) + + err := s.testAddPCRProfile(c, &testAddPCRProfileData{ + vars: makeMockVars(c, withMsSecureBootConfig(), withSbatLevel([]byte("sbat,1,2022052400\ngrub,2\n")), withDeployedModeDisabled()), + log: efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, + // This is the weird case some user have AuditMode/DeployedMode variables are defined, but not measured + DisableDeployedMode: false, + }), + alg: tpm2.HashAlgorithmSHA256, + loadSequences: NewImageLoadSequences( + SnapModelParams(testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ + "authority-id": "fake-brand", + "series": "16", + "brand-id": "fake-brand", + "model": "fake-model", + "grade": "secured", + }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij")), + ).Append( + NewImageLoadActivity(shim).Loads( + NewImageLoadActivity(grub, KernelCommandlineParams("console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=recover")).Loads( + NewImageLoadActivity(grub, KernelCommandlineParams("console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run")).Loads( + NewImageLoadActivity(runKernel), + ), + NewImageLoadActivity(recoverKernel), + ), + ), + ), + expected: []tpm2.PCRValues{ + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), + }, + }, + { + tpm2.HashAlgorithmSHA256: { + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), + }, + }, + }, + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile(), WithAutoAllowSecureBootUserMode()) + c.Check(err, IsNil) +} diff --git a/efi/secureboot.go b/efi/secureboot.go index 28615747..9311b564 100644 --- a/efi/secureboot.go +++ b/efi/secureboot.go @@ -320,7 +320,8 @@ const ( // includeSecureBootUserModeParamKey is used to indicate that user mode related // measurements should be included in the secure boot PCR profile if the system is // in user mode. - includeSecureBootUserModeParamKey = "include_secure_boot_user_mode" + includeSecureBootUserModeParamKey = "include_secure_boot_user_mode" + autoIncludeSecureBootUserModeParamKey = "auto_include_secure_boot_user_mode" ) type allowSecureBootUserModeOption struct{} @@ -343,6 +344,26 @@ func (o allowSecureBootUserModeOption) ApplyOptionTo(visitor internal_efi.PCRPro return nil } +type autoAllowSecureBootUserModeOption struct{} + +func (o autoAllowSecureBootUserModeOption) ApplyOptionTo(visitor internal_efi.PCRProfileOptionVisitor) error { + visitor.AddImageLoadParams(func(params ...loadParams) []loadParams { + var out []loadParams + for _, v := range []bool{false, true} { + var newParams []loadParams + for _, p := range params { + newParams = append(newParams, p.Clone()) + } + for _, p := range newParams { + p[autoIncludeSecureBootUserModeParamKey] = v + } + out = append(out, newParams...) + } + return out + }) + return nil +} + // WithAllowSecureBootUserMode can be supplied to AddPCRProfile to allow for secure boot // PCR profiles that support user mode to be generated on systems where user mode is // currently enabled. This is opt-in to ensure that a system that was originally in @@ -355,3 +376,15 @@ func (o allowSecureBootUserModeOption) ApplyOptionTo(visitor internal_efi.PCRPro func WithAllowSecureBootUserMode() PCRProfileOption { return allowSecureBootUserModeOption{} } + +// WithAutoAllowSecureBootUserMode is like WithAllowSecureBootUserMode but will +// only expect measurements if the event log contains them. +// The variables still need to also be defined. +// For Ubuntu Core users there are hardware that define AuditMode/DeployedMode variables +// and still fail to measure that in PCR7. So we need to detect that hardware from the event +// log. +// +// This option should only be used by Ubuntu Core. +func WithAutoAllowSecureBootUserMode() PCRProfileOption { + return autoAllowSecureBootUserModeOption{} +}