Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

overlord/fdestate/backend/reseal.go: factor FDE hook and TPM resealing #14674

Open
wants to merge 7 commits into
base: fde-manager-features
Choose a base branch
from

Conversation

valentindavid
Copy link
Contributor

Instead of splitting completely FDE hook and TPM resealing, we split the calculation of role parameters, udpate the state, then do the resealing based on that state.

This depends on #14305

@github-actions github-actions bot added the Run Nested -auto- Label automatically added in case nested tests need to be executed label Oct 25, 2024
@valentindavid valentindavid force-pushed the valentindavid/factorize-hook-tpm-resealing branch from a305470 to 75bd290 Compare October 25, 2024 13:42
Copy link

codecov bot commented Oct 25, 2024

Codecov Report

Attention: Patch coverage is 65.95745% with 64 lines in your changes missing coverage. Please review.

Please upload report for BASE (fde-manager-features@bd4c3ff). Learn more about missing BASE report.

Files with missing lines Patch % Lines
overlord/fdestate/backend/reseal.go 66.39% 25 Missing and 16 partials ⚠️
overlord/fdestate/fdestate.go 60.00% 8 Missing and 4 partials ⚠️
overlord/fdestate/fdemgr.go 69.44% 8 Missing and 3 partials ⚠️
Additional details and impacted files
@@                   Coverage Diff                   @@
##             fde-manager-features   #14674   +/-   ##
=======================================================
  Coverage                        ?   78.81%           
=======================================================
  Files                           ?     1093           
  Lines                           ?   147878           
  Branches                        ?        0           
=======================================================
  Hits                            ?   116556           
  Misses                          ?    24037           
  Partials                        ?     7285           
Flag Coverage Δ
unittests 78.81% <65.95%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@valentindavid valentindavid added FDE Manager Pull requests that target FDE manager branch Run nested The PR also runs tests inluded in nested suite labels Oct 25, 2024
@valentindavid valentindavid force-pushed the valentindavid/factorize-hook-tpm-resealing branch from 75bd290 to 9ffe2f3 Compare November 5, 2024 10:05
@valentindavid valentindavid marked this pull request as ready for review November 5, 2024 10:05
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion

Comment on lines 63 to 64
type StateUpdater func(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
type StateGetter func(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it make sense to combine these two into an interface and have FDEManager implement it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I will do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though, I will need to wrap it since we need to handle the unlocker.

Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines 63 to 68
type FDEState interface {
UpdateState(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
GetState(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type FDEState interface {
UpdateState(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
GetState(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error)
}
type FDEStateManager interface {
Update(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
Get(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error)
}

depending on how useful it would be for mocking in the tests the interface can be split into *Getter (eg. doReseal only uses Get(), and *Updater and then have one interface combining the two. Although looking at test changes it's probably not worth it.

@valentindavid valentindavid force-pushed the valentindavid/factorize-hook-tpm-resealing branch from 4fab00f to b467e2d Compare November 7, 2024 15:19
Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did a pass, bunch of comments and questions

return err
}

_, recoveryModels, recoveryPCRProfile, err := manager.Get("recover", "system-save")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gadget has constants for things like "system-save", I even wonder if we should give them a type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we should. I think we have FIXMEs on the Set calls.

type StateUpdater func(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
type FDEStateManager interface {
Update(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error
Get(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not something we can do much about but is indeed not great that both things are called role, we need to be very careful

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use types at least. Again, this is related to the FIXMEs on calls to Update.

}
}

func resealKeyForBootChainsFDEHook(manager FDEStateManager, method device.SealingMethod, rootdir string, inputs resealInputs, opts resealOptions) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this functions needs a new name no? is not really doing the reseal anymore?

inputs resealInputs,
opts resealOptions,
) error {
func resealKeyForBootChainsTPM(manager FDEStateManager, method device.SealingMethod, rootdir string, inputs resealInputs, opts resealOptions) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Comment on lines 136 to 137
unlocker boot.Unlocker
m *FDEManager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be simplified to:

{
FDEManager
unlock bool
}

as we just check if unlocker is nil


func (m *unlockedStateManager) Update(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error {
if m.unlocker != nil {
m.m.state.Lock()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would avoid the m.m here

return updateParameters(m.m.state, role, containerRole, bootModes, models, tpmPCRProfile)
}

func (m *unlockedStateManager) Get(role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs testing

var s FdeState
err = st.Get(fdeStateKey, &s)
if err != nil {
return nil, nil, nil, err
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as this is not tested

Comment on lines 367 to 370
return nil
}

func getParameters(st *state.State, role string, containerRole string) (bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte, err error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have the manager now where get/updateParameters are called? can they become simply method on it?

}

func (m *unlockedStateManager) Update(role string, containerRole string, bootModes []string, models []secboot.ModelForSealing, tpmPCRProfile []byte) error {
if m.unlocker != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so now we unlock to run reseal below, then lock/unlock to update, then lock/unlock again to get, then relock? can we avoid or coalesce some of these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have to bring the unlocker down. I think what we need to do use unlock while we calculate the profile. This is what takes time. Then we do not have to relock to Get/Update

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it better to save the state after the Update or not? unlock does that too

otherwise we could give FDEStateManger interface a Unlock() (relock func()) method and indeed use it in the backend only when needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good. I will try that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed to do the unlocking only when calculating the profile. And put the unlocker into the FDEStateManager abstraction.

Instead of splitting completely FDE hook and TPM resealing, we split
the calculation of role parameters, udpate the state, then do
the resealing based on that state.
@valentindavid valentindavid force-pushed the valentindavid/factorize-hook-tpm-resealing branch from 1a50feb to f981410 Compare November 8, 2024 14:49
@valentindavid valentindavid force-pushed the valentindavid/factorize-hook-tpm-resealing branch from f981410 to b753897 Compare November 8, 2024 15:01
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, a few more cleanup comments

return m.GetParameters(role, containerRole)
}

func (m *unlockedStateManager) Unlock() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it feels like returning the relock function or a nop function would be a bit simpler that needing to have a relock member?

@@ -200,7 +191,7 @@ func resealKeys(
pbcJSON, _ := json.Marshal(pbc)
logger.Debugf("resealing (%d) to boot chains: %s", nextCount, pbcJSON)

err := resealRunObjectKeys(updateState, runOnlyPbc, pbc, inputs.signatureDBUpdate, authKeyFile, params.RoleToBlName)
err := resealRunObjectKeys(manager, runOnlyPbc, pbc, inputs.signatureDBUpdate, params.RoleToBlName)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems these function also needs a new name, like updateRunObjectKeysProtectionProfile or something like that?

@@ -227,7 +218,7 @@ func resealKeys(
rpbcJSON, _ := json.Marshal(rpbc)
logger.Debugf("resealing (%d) to recovery boot chains: %s", nextFallbackCount, rpbcJSON)

err := resealFallbackObjectKeys(updateState, rpbc, inputs.signatureDBUpdate, authKeyFile, params.RoleToBlName)
err := resealFallbackObjectKeys(manager, rpbc, inputs.signatureDBUpdate, params.RoleToBlName)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FDE Manager Pull requests that target FDE manager branch Run Nested -auto- Label automatically added in case nested tests need to be executed Run nested The PR also runs tests inluded in nested suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants