From 4384e8be01a9875d99ef341a32581694bc259893 Mon Sep 17 00:00:00 2001 From: Chris Coulson Date: Fri, 22 Mar 2024 09:08:46 +0000 Subject: [PATCH] efi: add WithKernelConfigProfile option to AddPCRProfile This replaces the separate calls to AddSystemdStubProfile and tpm2.AddSnapModelProfile, which are now deprecated and will be removed in a follow-up PR. --- efi/efi.go | 1 + efi/efi_test.go | 11 +- efi/export_test.go | 1 + efi/fw_load_handler.go | 3 + efi/fw_load_handler_test.go | 12 +- efi/grub_load_handler_test.go | 8 +- efi/pcr_profile.go | 12 ++ efi/pcr_profile_test.go | 257 +++++++++++++++++++++----------- efi/sdstub_policy.go | 2 + efi/sdstub_policy_test.go | 8 +- efi/shim_load_handler_test.go | 4 +- efi/uc_uki_load_handler.go | 39 ++++- efi/uc_uki_load_handler_test.go | 179 ++++++++++++++++++++++ tpm2/export_test.go | 1 - tpm2/snapmodel_policy.go | 44 +++++- tpm2/snapmodel_policy_test.go | 4 +- 16 files changed, 473 insertions(+), 113 deletions(-) create mode 100644 efi/uc_uki_load_handler_test.go diff --git a/efi/efi.go b/efi/efi.go index d8d394e9..cf1a4aa0 100644 --- a/efi/efi.go +++ b/efi/efi.go @@ -22,4 +22,5 @@ package efi const ( bootManagerCodePCR = 4 // Boot Manager Code and Boot Attempts PCR secureBootPCR = 7 // Secure Boot Policy Measurements PCR + kernelConfigPCR = 12 ) diff --git a/efi/efi_test.go b/efi/efi_test.go index ad47bda1..5b53e171 100644 --- a/efi/efi_test.go +++ b/efi/efi_test.go @@ -77,22 +77,29 @@ type mockPcrBranchEvent struct { type mockPcrBranchContext struct { PcrProfileContext + params LoadParams vars VarReadWriter fc *FwContext sc *ShimContext events []*mockPcrBranchEvent } -func newMockPcrBranchContext(pc PcrProfileContext, vars VarReadWriter) *mockPcrBranchContext { +func newMockPcrBranchContext(pc PcrProfileContext, params *LoadParams, vars VarReadWriter) *mockPcrBranchContext { + if params == nil { + params = new(LoadParams) + } return &mockPcrBranchContext{ PcrProfileContext: pc, + params: *params, vars: vars, fc: new(FwContext), sc: new(ShimContext), } } -func (*mockPcrBranchContext) Params() *LoadParams { return nil } +func (c *mockPcrBranchContext) Params() *LoadParams { + return &c.params +} func (c *mockPcrBranchContext) Vars() VarReadWriter { return c.vars diff --git a/efi/export_test.go b/efi/export_test.go index e75402e4..f6bfe58d 100644 --- a/efi/export_test.go +++ b/efi/export_test.go @@ -28,6 +28,7 @@ import ( const ( BootManagerCodeProfile = bootManagerCodeProfile GrubChainloaderUsesShimProtocol = grubChainloaderUsesShimProtocol + KernelConfigProfile = kernelConfigProfile SecureBootPolicyProfile = secureBootPolicyProfile ShimFixVariableAuthorityEventsMatchSpec = shimFixVariableAuthorityEventsMatchSpec ShimHasSbatRevocationManagement = shimHasSbatRevocationManagement diff --git a/efi/fw_load_handler.go b/efi/fw_load_handler.go index ffc8e200..db6962ec 100644 --- a/efi/fw_load_handler.go +++ b/efi/fw_load_handler.go @@ -197,6 +197,9 @@ func (h *fwLoadHandler) MeasureImageStart(ctx pcrBranchContext) error { if ctx.Flags()&bootManagerCodeProfile > 0 { h.measureBootManagerCodePreOS(ctx) } + if ctx.Flags()&kernelConfigProfile > 0 { + ctx.ResetPCR(kernelConfigPCR) + } return nil } diff --git a/efi/fw_load_handler_test.go b/efi/fw_load_handler_test.go index 6df11ba5..46e9cc16 100644 --- a/efi/fw_load_handler_test.go +++ b/efi/fw_load_handler_test.go @@ -53,7 +53,7 @@ func (s *fwLoadHandlerSuite) testMeasureImageStart(c *C, data *testFwMeasureImag collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(data.vars, nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: data.alg, - flags: data.flags}, collector.Next()) + flags: data.flags}, nil, collector.Next()) handler := NewFwLoadHandler(efitest.NewLog(c, data.logOptions)) c.Check(handler.MeasureImageStart(ctx), IsNil) @@ -211,7 +211,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog1(c *C) { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, collector.Next()) + flags: SecureBootPolicyProfile}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -234,7 +234,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog2(c *C) { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, collector.Next()) + flags: SecureBootPolicyProfile}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -260,7 +260,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog3(c *C) { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, collector.Next()) + flags: SecureBootPolicyProfile}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -286,7 +286,7 @@ func (s *fwLoadHandlerSuite) TestMeasureImageStartErrBadLog4(c *C) { collector := NewRootVarsCollector(efitest.NewMockHostEnvironment(makeMockVars(c, withMsSecureBootConfig()), nil)) ctx := newMockPcrBranchContext(&mockPcrProfileContext{ alg: tpm2.HashAlgorithmSHA256, - flags: SecureBootPolicyProfile}, collector.Next()) + flags: SecureBootPolicyProfile}, nil, collector.Next()) log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}}) for i, event := range log.Events { @@ -323,7 +323,7 @@ func (s *fwLoadHandlerSuite) testMeasureImageLoad(c *C, data *testFwMeasureImage alg: data.alg, flags: data.flags, handlers: s, - }, nil) + }, nil, nil) if data.fc != nil { ctx.fc = data.fc } diff --git a/efi/grub_load_handler_test.go b/efi/grub_load_handler_test.go index cb0f0567..1948954f 100644 --- a/efi/grub_load_handler_test.go +++ b/efi/grub_load_handler_test.go @@ -44,7 +44,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_7(c *C) { alg: tpm2.HashAlgorithmSHA256, flags: SecureBootPolicyProfile, handlers: s, - }, nil) + }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ Name: Db, Contents: msDb(c), @@ -73,7 +73,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadUbuntuUsesShim15_6(c *C) { alg: tpm2.HashAlgorithmSHA256, flags: SecureBootPolicyProfile, handlers: s, - }, nil) + }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ Name: Db, Contents: msDb(c), @@ -102,7 +102,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShim(c *C) { alg: tpm2.HashAlgorithmSHA256, flags: SecureBootPolicyProfile, handlers: s, - }, nil) + }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ Name: Db, Contents: append(msDb(c), efitest.NewSignatureListX509(c, canonicalCACert, testOwnerGuid)), @@ -131,7 +131,7 @@ func (s *grubLoadHandlerSuite) TestMeasureImageLoadNoShimError(c *C) { alg: tpm2.HashAlgorithmSHA256, flags: SecureBootPolicyProfile, handlers: s, - }, nil) + }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ Name: Db, Contents: msDb(c), diff --git a/efi/pcr_profile.go b/efi/pcr_profile.go index 10f77c16..7cf2159b 100644 --- a/efi/pcr_profile.go +++ b/efi/pcr_profile.go @@ -135,6 +135,17 @@ func WithBootManagerCodeProfile() PCRProfileOption { return pcrProfileSetFlagsOption(bootManagerCodeProfile) } +// WithKernelConfigProfile adds the kernel config profile. This binds a policy to a +// set of externally supplied commandlines. On Ubuntu Core, this also binds a policy +// to a set of model assertions and the initrd phase of the boot. +// +// 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) +} + // AddPCRProfile adds a profile defined by the supplied options to the supplied // secboot_tpm2.PCRProtectionProfileBranch, using the specified digest algorithm // for the PCR digest. The generated profile is defined by the supplied load @@ -154,6 +165,7 @@ type pcrProfileFlags int const ( secureBootPolicyProfile pcrProfileFlags = 1 << iota bootManagerCodeProfile + kernelConfigProfile ) type pcrProfileGenerator struct { diff --git a/efi/pcr_profile_test.go b/efi/pcr_profile_test.go index d494911c..cc804af6 100644 --- a/efi/pcr_profile_test.go +++ b/efi/pcr_profile_test.go @@ -668,10 +668,18 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( - NewImageLoadActivity(grub).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), @@ -681,18 +689,20 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20(c *C) { expected: []tpm2.PCRValues{ { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 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"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, IsNil) } @@ -710,10 +720,18 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20WithTryKernel(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( - NewImageLoadActivity(grub).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(runKernel1), NewImageLoadActivity(runKernel2), ), @@ -724,24 +742,27 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20WithTryKernel(c *C) { expected: []tpm2.PCRValues{ { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "407f697575347ec33bd66d5a6311e994de513abc28bebe8e4cfae5c20fe67e38"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 4: testutil.DecodeHexString(c, "407f697575347ec33bd66d5a6311e994de513abc28bebe8e4cfae5c20fe67e38"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, IsNil) } @@ -762,18 +783,26 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20ShimUpdate(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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(shim1).Loads( - NewImageLoadActivity(grub).Loads( - NewImageLoadActivity(grub).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), ), ), NewImageLoadActivity(shim2).Loads( - NewImageLoadActivity(grub).Loads( - NewImageLoadActivity(grub).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), @@ -784,45 +813,51 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20ShimUpdate(c *C) { // Shim 15.4 branches { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), - 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), + 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), - 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), + 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, // Shim 15.7 branches { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 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"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, // Shim 15.4 branches after applying SBAT update from shim 15.7 - note that PCR4 values are identical but // PCR7 is updated because the value of SbatLevel changes. These branches facilitate potential A/B updating shim { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), - 7: testutil.DecodeHexString(c, "6fc916d63dbb2efa1d6179fc105ae48451ad5d09218312157762eced9d1bdfbb"), + 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), + 7: testutil.DecodeHexString(c, "6fc916d63dbb2efa1d6179fc105ae48451ad5d09218312157762eced9d1bdfbb"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), - 7: testutil.DecodeHexString(c, "6fc916d63dbb2efa1d6179fc105ae48451ad5d09218312157762eced9d1bdfbb"), + 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), + 7: testutil.DecodeHexString(c, "6fc916d63dbb2efa1d6179fc105ae48451ad5d09218312157762eced9d1bdfbb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, IsNil) } @@ -841,18 +876,26 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20ShimUpdateFromPreSbat(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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(shim1).Loads( - NewImageLoadActivity(grub).Loads( - NewImageLoadActivity(grub).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), ), ), NewImageLoadActivity(shim2).Loads( - NewImageLoadActivity(grub).Loads( - NewImageLoadActivity(grub).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), @@ -863,31 +906,35 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20ShimUpdateFromPreSbat(c *C) { // Shim 15 { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "68e3d6ce7f8bf9f647629bd926486a0309b28efcb2e74c2bb517ee45dd0081ca"), - 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 4: testutil.DecodeHexString(c, "68e3d6ce7f8bf9f647629bd926486a0309b28efcb2e74c2bb517ee45dd0081ca"), + 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "42eeb4127f3732e54119df9a6c0383b63fbca39bc715edefc4bebdc62bbe0f7b"), - 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 4: testutil.DecodeHexString(c, "42eeb4127f3732e54119df9a6c0383b63fbca39bc715edefc4bebdc62bbe0f7b"), + 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, // Shim 15.4 branches { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), - 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 4: testutil.DecodeHexString(c, "d196042b85e14fd009817abda16522e1fb32b19617e68d4688d0d435b24b5d02"), + 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), - 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 4: testutil.DecodeHexString(c, "96c0ede7bb07853e327c4eaf64ec4341d4eeaa833c80ae1ed865fba4cde43ba7"), + 7: testutil.DecodeHexString(c, "98f515726b235c9226a5c0d4cc2d421e6ce22f35b6652b2fbf9005fc12202d66"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, IsNil) } @@ -905,10 +952,18 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20SbatPolicyLatest(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( - NewImageLoadActivity(grub).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), @@ -919,31 +974,35 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20SbatPolicyLatest(c *C) { // Branches with current SbatLevel { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 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"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, // Branches with updated SbatLevel { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "ecb8e9facbb7f23594b887e3df384cf998d800400bae4acb1efe5b7e7e2a0029"), + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "ecb8e9facbb7f23594b887e3df384cf998d800400bae4acb1efe5b7e7e2a0029"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), - 7: testutil.DecodeHexString(c, "ecb8e9facbb7f23594b887e3df384cf998d800400bae4acb1efe5b7e7e2a0029"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "ecb8e9facbb7f23594b887e3df384cf998d800400bae4acb1efe5b7e7e2a0029"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithShimSbatPolicyLatest()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile(), WithShimSbatPolicyLatest()) c.Check(err, IsNil) } @@ -959,10 +1018,18 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20PreSbat(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( - NewImageLoadActivity(grub).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(kernel), ), NewImageLoadActivity(kernel), @@ -972,18 +1039,20 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20PreSbat(c *C) { expected: []tpm2.PCRValues{ { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "39edc30b02bd577c7b36fe3d52953894ad3781611428082df5af0a9c04421398"), - 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 4: testutil.DecodeHexString(c, "39edc30b02bd577c7b36fe3d52953894ad3781611428082df5af0a9c04421398"), + 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "c9daf36f478b0636bee66330ccb5c5878db5f41fa3a94df796b88e3c2744bac9"), - 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 4: testutil.DecodeHexString(c, "c9daf36f478b0636bee66330ccb5c5878db5f41fa3a94df796b88e3c2744bac9"), + 7: testutil.DecodeHexString(c, "65df349cba09824e925f4563877f2e0b145ce929db0cc1d8a665014857e9e7e9"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, IsNil) } @@ -1000,10 +1069,18 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20WithDbxUpdate(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( - NewImageLoadActivity(grub).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), @@ -1014,31 +1091,35 @@ func (s *pcrProfileSuite) TestAddPCRProfileUC20WithDbxUpdate(c *C) { // Pre-dbx update branches: { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 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"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "3d65dbe406e9427d402488ea4f87e07e8b584c79c578a735d48d21a6405fc8bb"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, // Post-dbx update branches: { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), - 7: testutil.DecodeHexString(c, "51d90abb35648752a0b4866f8b4eb0e5b53113abea015b7576f8b5d373c62dae"), + 4: testutil.DecodeHexString(c, "bec6121586508581e08a41244944292ef452879f8e19c7f93d166e912c6aac5e"), + 7: testutil.DecodeHexString(c, "51d90abb35648752a0b4866f8b4eb0e5b53113abea015b7576f8b5d373c62dae"), + 12: testutil.DecodeHexString(c, "fd1000c6f691c3054e2ff5cfacb39305820c9f3534ba67d7894cb753aa85074b"), }, }, { tpm2.HashAlgorithmSHA256: { - 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), - 7: testutil.DecodeHexString(c, "51d90abb35648752a0b4866f8b4eb0e5b53113abea015b7576f8b5d373c62dae"), + 4: testutil.DecodeHexString(c, "c731a39b7fc6475c7d8a9264e704902157c7cee40c22f59fa1690ea99ff70c67"), + 7: testutil.DecodeHexString(c, "51d90abb35648752a0b4866f8b4eb0e5b53113abea015b7576f8b5d373c62dae"), + 12: testutil.DecodeHexString(c, "5b354c57a61bb9f71fcf596d7e9ef9e2e0d6f4ad8151c9f358e6f0aaa7823756"), }, }, }, - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithSignatureDBUpdates(&SignatureDBUpdate{Name: Dbx, Data: msDbxUpdate2})) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile(), WithSignatureDBUpdates(&SignatureDBUpdate{Name: Dbx, Data: msDbxUpdate2})) c.Check(err, IsNil) } @@ -1053,7 +1134,15 @@ func (s *pcrProfileSuite) TestAddPCRProfileLoadFailsFromLeafImage(c *C) { Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA1}, }), alg: tpm2.HashAlgorithmSHA256, - loadSequences: NewImageLoadSequences().Append( + 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).Loads( NewImageLoadActivity(grub).Loads( @@ -1064,6 +1153,6 @@ func (s *pcrProfileSuite) TestAddPCRProfileLoadFailsFromLeafImage(c *C) { ), ), ), - }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile()) + }, WithSecureBootPolicyProfile(), WithBootManagerCodeProfile(), WithKernelConfigProfile()) c.Check(err, ErrorMatches, `cannot measure image 0x[[:xdigit:]]{10}: cannot measure image load: kernel is a leaf image`) } diff --git a/efi/sdstub_policy.go b/efi/sdstub_policy.go index 9138cfc8..ff4bf531 100644 --- a/efi/sdstub_policy.go +++ b/efi/sdstub_policy.go @@ -49,6 +49,8 @@ type SystemdStubProfileParams struct { // The PCR index that the EFI stub measures the kernel commandline too can be specified via the PCRIndex field of params. // // The set of kernel commandlines to add to the PCRProtectionProfile is specified via the KernelCmdlines field of params. +// +// Deprecated: use [AddPCRProfile] with the [WithKernelConfigProfile] option. func AddSystemdStubProfile(branch *secboot_tpm2.PCRProtectionProfileBranch, params *SystemdStubProfileParams) error { if params.PCRIndex < 0 { return errors.New("invalid PCR index") diff --git a/efi/sdstub_policy_test.go b/efi/sdstub_policy_test.go index 8aaed4e6..7f80c6ac 100644 --- a/efi/sdstub_policy_test.go +++ b/efi/sdstub_policy_test.go @@ -70,10 +70,10 @@ func (s *sdstubPolicySuite) testAddSystemdStubProfile(c *C, data *testAddSystemd c.Check(pcrs, tpm2_testutil.TPMValueDeepEquals, expectedPcrs) c.Check(digests, DeepEquals, expectedDigests) - if c.Failed() { - c.Logf("Profile:\n%s", profile) - c.Logf("Values:\n%s", tpm2test.FormatPCRValuesFromPCRProtectionProfile(profile, nil)) - } + //if c.Failed() { + c.Logf("Profile:\n%s", profile) + c.Logf("Values:\n%s", tpm2test.FormatPCRValuesFromPCRProtectionProfile(profile, nil)) + //} } func (s *sdstubPolicySuite) TestAddSystemdStubProfileUC20(c *C) { diff --git a/efi/shim_load_handler_test.go b/efi/shim_load_handler_test.go index 034d6028..7f3846e1 100644 --- a/efi/shim_load_handler_test.go +++ b/efi/shim_load_handler_test.go @@ -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}, collector.Next()) + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: data.alg, flags: data.flags}, nil, collector.Next()) handler := &ShimLoadHandler{ Flags: data.shimFlags, @@ -458,7 +458,7 @@ func (s *shimLoadHandlerSuite) testMeasureImageLoad(c *C, data *testShimMeasureI alg: data.alg, flags: data.flags, handlers: s, - }, nil) + }, nil, nil) ctx.FwContext().Db = &SecureBootDB{ Name: Db, Contents: data.db, diff --git a/efi/uc_uki_load_handler.go b/efi/uc_uki_load_handler.go index 8557d49e..bee84fdd 100644 --- a/efi/uc_uki_load_handler.go +++ b/efi/uc_uki_load_handler.go @@ -21,6 +21,10 @@ package efi import ( "errors" + "fmt" + + "github.com/canonical/tcglog-parser" + "github.com/snapcore/secboot/tpm2" ) type ubuntuCoreUKILoadHandler struct{} @@ -29,9 +33,38 @@ func newUbuntuCoreUKILoadHandler(_ peImageHandle) (imageLoadHandler, error) { return new(ubuntuCoreUKILoadHandler), nil } -func (h *ubuntuCoreUKILoadHandler) MeasureImageStart(_ pcrBranchContext) error { - // TODO: Add stuff that the kernel measures here - // for now clients can continue using AddSystemdStubProfile +func (h *ubuntuCoreUKILoadHandler) MeasureImageStart(ctx pcrBranchContext) error { + // TODO: maybe handle the kernel boot PCR (11) in the future because this + // also contains the boot phase, which could replace the additional measurement + // we make to PCR12. This does also contain the kernel digest, although this is + // 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 { + // the stub doesn't measure anything if the commandline is empty + if ctx.Params().KernelCommandline != "" { + ctx.ExtendPCR(kernelConfigPCR, + tcglog.ComputeSystemdEFIStubCommandlineDigest(ctx.PCRAlg().GetHash(), ctx.Params().KernelCommandline)) + } + + // TODO: handle credentials, confexts and commandline addons if we need + // then in the future. These all go into kernelConfigPCR + } + + // TODO: handle sysexts if we need them in the future, which go to the sysext PCR (13). + + if ctx.Flags()&kernelConfigProfile > 0 { + if ctx.Params().SnapModel == nil { + return errors.New("snap model must be set using SnapModelParams") + } + ctx.ExtendPCR(kernelConfigPCR, tpm2.ComputeSnapSystemEpochDigest(ctx.PCRAlg(), 0)) + modelDigest, err := tpm2.ComputeSnapModelDigest(ctx.PCRAlg(), ctx.Params().SnapModel) + if err != nil { + return fmt.Errorf("cannot compute model digest: %w", err) + } + ctx.ExtendPCR(kernelConfigPCR, modelDigest) + } + return nil } diff --git a/efi/uc_uki_load_handler_test.go b/efi/uc_uki_load_handler_test.go new file mode 100644 index 00000000..206d4217 --- /dev/null +++ b/efi/uc_uki_load_handler_test.go @@ -0,0 +1,179 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2023 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 efi_test + +import ( + . "gopkg.in/check.v1" + + "github.com/canonical/go-tpm2" + . "github.com/snapcore/secboot/efi" + "github.com/snapcore/secboot/internal/testutil" +) + +type ucUkiLoadHandlerSuite struct{} + +var _ = Suite(&ucUkiLoadHandlerSuite{}) + +type testUCUKIMeasureImageStartParams struct { + alg tpm2.HashAlgorithmId + flags PcrProfileFlags + params LoadParams + + expectedEvents []*mockPcrBranchEvent +} + +func (s *ucUkiLoadHandlerSuite) testMeasureImageStart(c *C, params *testUCUKIMeasureImageStartParams) { + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: params.alg, flags: params.flags}, ¶ms.params, nil) + + var handler UbuntuCoreUKILoadHandler + c.Check(handler.MeasureImageStart(ctx), IsNil) + c.Check(ctx.events, DeepEquals, params.expectedEvents) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStart(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA256, + flags: KernelConfigProfile, + params: LoadParams{ + KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", + SnapModel: 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"), + }, + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "2dc1d5c9791826cc681892421b14d36e5dd0241de367536f3ba5f7d9caa70e48")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d64df514d7ac57c1a28c5f2a3abc39340d9b7fe3f76cc3acc991d418f095d5b0")}, + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartDifferentCommandline(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA256, + flags: KernelConfigProfile, + params: LoadParams{ + KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=recover", + SnapModel: 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"), + }, + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "1295ed0b7ea5bf326d55223b446ebfeef10e487568dc0fee09edcce157c9c236")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d64df514d7ac57c1a28c5f2a3abc39340d9b7fe3f76cc3acc991d418f095d5b0")}, + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartDifferentModel(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA256, + flags: KernelConfigProfile, + params: LoadParams{ + KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", + SnapModel: testutil.MakeMockCore20ModelAssertion(c, map[string]interface{}{ + "authority-id": "fake-brand", + "series": "16", + "brand-id": "fake-brand", + "model": "other-model", + "grade": "secured", + }, "Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij"), + }, + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "2dc1d5c9791826cc681892421b14d36e5dd0241de367536f3ba5f7d9caa70e48")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "3be5bf8ae76a9eea01f016a69061ff2bf914b63a3b50436a3e997cc6e50393eb")}, + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoKernelConfig(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA256, + params: LoadParams{ + KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", + SnapModel: 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"), + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartSHA1(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA1, + flags: KernelConfigProfile, + params: LoadParams{ + KernelCommandline: "console=ttyS0 console=tty1 panic=-1 systemd.gpt_auto=0 snapd_recovery_mode=run", + SnapModel: 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"), + }, + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "f4e8b2c40f233509dce97fe70d20a474e8a3ec7e")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "9069ca78e7450a285173431b3e52c5c25299e473")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "28be03fcfc8de01cbf2237a3c41d22ffa81bee2f")}, + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoCommandline(c *C) { + s.testMeasureImageStart(c, &testUCUKIMeasureImageStartParams{ + alg: tpm2.HashAlgorithmSHA256, + flags: KernelConfigProfile, + params: LoadParams{ + SnapModel: 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"), + }, + expectedEvents: []*mockPcrBranchEvent{ + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119")}, + {pcr: 12, eventType: mockPcrBranchExtendEvent, digest: testutil.DecodeHexString(c, "d64df514d7ac57c1a28c5f2a3abc39340d9b7fe3f76cc3acc991d418f095d5b0")}, + }, + }) +} + +func (s *ucUkiLoadHandlerSuite) TestMeasureImageStartNoSnapModel(c *C) { + ctx := newMockPcrBranchContext(&mockPcrProfileContext{alg: tpm2.HashAlgorithmSHA256, flags: KernelConfigProfile}, nil, nil) + + var handler UbuntuCoreUKILoadHandler + c.Check(handler.MeasureImageStart(ctx), ErrorMatches, `snap model must be set using SnapModelParams`) +} diff --git a/tpm2/export_test.go b/tpm2/export_test.go index 85a4a8c1..c87ba809 100644 --- a/tpm2/export_test.go +++ b/tpm2/export_test.go @@ -40,7 +40,6 @@ var ( ComputeV1PcrPolicyRefFromCounterName = computeV1PcrPolicyRefFromCounterName ComputeV3PcrPolicyCounterAuthPolicies = computeV3PcrPolicyCounterAuthPolicies ComputeV3PcrPolicyRef = computeV3PcrPolicyRef - ComputeSnapModelDigest = computeSnapModelDigest DeriveV3PolicyAuthKey = deriveV3PolicyAuthKey ErrSessionDigestNotFound = errSessionDigestNotFound IsPolicyDataError = isPolicyDataError diff --git a/tpm2/snapmodel_policy.go b/tpm2/snapmodel_policy.go index 85901104..c8da2cdf 100644 --- a/tpm2/snapmodel_policy.go +++ b/tpm2/snapmodel_policy.go @@ -35,7 +35,16 @@ import ( const zeroSnapSystemEpoch uint32 = 0 -func computeSnapSystemEpochDigest(alg tpm2.HashAlgorithmId, epoch uint32) tpm2.Digest { +// ComputeSnapSystemEpoch computes a measurement digest for the supplied epoch, as +// measured by snap-bootstrap, and is used to provide a useful escape hatch for potential +// vulnerabilities in snap-bootstrap. +// +// The digest is computed as: (where H is the supplied digest algorithm): +// +// digest = H(uint32(epoch)) +// +// The current epoch as measured by [MeasureSnapSystemEpochToTPM] is 0. +func ComputeSnapSystemEpochDigest(alg tpm2.HashAlgorithmId, epoch uint32) tpm2.Digest { h := alg.NewHash() binary.Write(h, binary.LittleEndian, epoch) return h.Sum(nil) @@ -119,6 +128,30 @@ func computeSnapModelDigest(newHash func() (snapModelHasher, error), model secbo return h.Complete() } +// ComputeSnapModelDigest computes a measurement digest for the supplied snap model. +// +// The digest is computed as follows (where H is the supplied digest algorithm): +// +// digest1 = H(tpm2.HashAlgorithmSHA384 || sign-key-sha3-384 || brand-id) +// digest2 = H(digest1 || model) +// digest = H(digest2 || series || grade) +// +// The signing key digest algorithm is encoded in little-endian format, and the sign-key-sha3-384 +// field is hashed in decoded (binary) form. The brand-id, model and series fields are hashed +// without null terminators. The grade field is encoded as the 32 bits from [github.com/snapcore/snapd/asserts.ModelGrade.Code] +// in little-endian format. If the model is a classic one, the grade is bitwise-ORd with [secboot.ClassicModelGradeMask] +// +// The current implementation incorrectly encodes the public key digest algorithm as SHA-384 +// when it should be SHA3-384, although the algorithm identifier is really there as a length +// prefix, so this is ok. +// +// Separate extend operations are used because brand-id, model and series are variable length. +func ComputeSnapModelDigest(alg tpm2.HashAlgorithmId, model secboot.SnapModel) (tpm2.Digest, error) { + return computeSnapModelDigest(func() (snapModelHasher, error) { + return &goSnapModelHasher{alg.NewHash()}, nil + }, model) +} + // SnapModelProfileParams provides the parameters to AddSnapModelProfile. type SnapModelProfileParams struct { // PCRAlgorithm is the algorithm for which to compute PCR digests for. TPMs compliant with the "TCG PC Client Platform TPM Profile @@ -163,6 +196,9 @@ type SnapModelProfileParams struct { // The PCR index that snap-bootstrap measures the model to can be specified via the PCRIndex field of params. // // The set of models to add to the PCRProtectionProfile is specified via the Models field of params. +// +// Deprecated: use [github.com/snapcore/secboot/efi.AddPCRProfile] with the [github.com/snapcore/secboot/efi.WithKernelConfigProfile] +// option. func AddSnapModelProfile(branch *PCRProtectionProfileBranch, params *SnapModelProfileParams) error { if params.PCRIndex < 0 { return errors.New("invalid PCR index") @@ -171,7 +207,7 @@ func AddSnapModelProfile(branch *PCRProtectionProfileBranch, params *SnapModelPr return errors.New("no models provided") } - branch.ExtendPCR(params.PCRAlgorithm, params.PCRIndex, computeSnapSystemEpochDigest(params.PCRAlgorithm, zeroSnapSystemEpoch)) + branch.ExtendPCR(params.PCRAlgorithm, params.PCRIndex, ComputeSnapSystemEpochDigest(params.PCRAlgorithm, zeroSnapSystemEpoch)) bp := branch.AddBranchPoint() for _, model := range params.Models { @@ -194,7 +230,7 @@ func AddSnapModelProfile(branch *PCRProtectionProfileBranch, params *SnapModelPr } // MeasureSnapSystemEpochToTPM measures a digest of uint32(0) to the specified PCR for all -// supported PCR banks. See the documentation for AddSnapModelProfile for more details. +// supported PCR banks. See the documentation for [ComputeSnapSystemEpoch] for more details. func MeasureSnapSystemEpochToTPM(tpm *Connection, pcrIndex int) error { seq, err := tpm.HashSequenceStart(nil, tpm2.HashAlgorithmNull) if err != nil { @@ -214,7 +250,7 @@ func MeasureSnapSystemEpochToTPM(tpm *Connection, pcrIndex int) error { } // MeasureSnapModelToTPM measures a digest of the supplied model assertion to the specified PCR -// for all supported PCR banks. See the documentation for AddSnapModelProfile for details of +// for all supported PCR banks. See the documentation for [ComputeSnapModelDigest] for details of // how the digest of the model is computed. func MeasureSnapModelToTPM(tpm *Connection, pcrIndex int, model secboot.SnapModel) error { pcrSelection, err := tpm.GetCapabilityPCRs(tpm.HmacSession().IncludeAttrs(tpm2.AttrAudit)) diff --git a/tpm2/snapmodel_policy_test.go b/tpm2/snapmodel_policy_test.go index 2eaac567..33834aa0 100644 --- a/tpm2/snapmodel_policy_test.go +++ b/tpm2/snapmodel_policy_test.go @@ -458,9 +458,7 @@ func (s *snapModelMeasureSuite) testMeasureSnapModelToTPMTest(c *C, data *testMe c.Assert(err, IsNil) for _, s := range pcrSelection { - snapModelDigest, err := ComputeSnapModelDigest(func() (SnapModelHasher, error) { - return &GoSnapModelHasher{s.Hash.NewHash()}, nil - }, data.model) + snapModelDigest, err := ComputeSnapModelDigest(s.Hash, data.model) c.Assert(err, IsNil) h := s.Hash.NewHash()