Skip to content

Commit

Permalink
fixup! secboot: run each key protected key generation in separate TPM…
Browse files Browse the repository at this point in the history
… context

Internally the secboot library closes the passed TPM connection, until
this is fixed, a separate connection per newTPMProtectedKey call fixes
this issue.

Signed-off-by: Zeyad Gouda <[email protected]>
  • Loading branch information
ZeyadYasser committed Jan 29, 2025
1 parent 890e7a3 commit d766ab6
Showing 1 changed file with 52 additions and 45 deletions.
97 changes: 52 additions & 45 deletions secboot/secboot_tpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ func ProvisionForCVM(initramfsUbuntuSeedDir string) error {
// connection for the same TPM device.
//
// FIXME: This approach is not thread safe and should be updated when fix lands in secboot.
func withSingleTPMConnection(fn func(tpm *sb_tpm2.Connection) error) error {
func withSingleTPMConnection(fn func(tpm *sb_tpm2.Connection)) error {
tpm, err := sbConnectToDefaultTPM()
if err != nil {
return fmt.Errorf("cannot connect to TPM: %v", err)
Expand All @@ -506,7 +506,8 @@ func withSingleTPMConnection(fn func(tpm *sb_tpm2.Connection) error) error {
}
defer func() { sb_tpm2.ConnectToTPM = old }()

return fn(tpm)
fn(tpm)
return nil
}

func kdfOptions(volumesAuth *device.VolumesAuthOptions) (sb.KDFOptions, error) {
Expand All @@ -532,7 +533,7 @@ func kdfOptions(volumesAuth *device.VolumesAuthOptions) (sb.KDFOptions, error) {
}
}

func newTPMProtectedKey(tpm *sb_tpm2.Connection, creationParams *sb_tpm2.ProtectKeyParams, volumesAuth *device.VolumesAuthOptions) (protectedKey *sb.KeyData, primaryKey sb.PrimaryKey, unlockKey sb.DiskUnlockKey, err error) {
func newTPMProtectedKey(creationParams *sb_tpm2.ProtectKeyParams, volumesAuth *device.VolumesAuthOptions) (protectedKey *sb.KeyData, primaryKey sb.PrimaryKey, unlockKey sb.DiskUnlockKey, err error) {
if volumesAuth != nil {
switch volumesAuth.Mode {
case device.AuthModePassphrase:
Expand All @@ -544,15 +545,25 @@ func newTPMProtectedKey(tpm *sb_tpm2.Connection, creationParams *sb_tpm2.Protect
ProtectKeyParams: *creationParams,
KDFOptions: kdfOptions,
}
protectedKey, primaryKey, unlockKey, err = sbNewTPMPassphraseProtectedKey(tpm, passphraseParams, volumesAuth.Passphrase)
tpmErr := withSingleTPMConnection(func(tpm *sb_tpm2.Connection) {
protectedKey, primaryKey, unlockKey, err = sbNewTPMPassphraseProtectedKey(tpm, passphraseParams, volumesAuth.Passphrase)
})
if tpmErr != nil {
return nil, nil, nil, tpmErr
}
case device.AuthModePIN:
// TODO: Implement PIN authentication mode.
return nil, nil, nil, fmt.Errorf("%q authentication mode is not implemented", device.AuthModePIN)
default:
return nil, nil, nil, fmt.Errorf("internal error: invalid authentication mode %q", volumesAuth.Mode)
}
} else {
protectedKey, primaryKey, unlockKey, err = sbNewTPMProtectedKey(tpm, creationParams)
tpmErr := withSingleTPMConnection(func(tpm *sb_tpm2.Connection) {
protectedKey, primaryKey, unlockKey, err = sbNewTPMProtectedKey(tpm, creationParams)
})
if tpmErr != nil {
return nil, nil, nil, tpmErr
}
}

return protectedKey, primaryKey, unlockKey, err
Expand All @@ -572,54 +583,50 @@ func SealKeys(keys []SealKeyRequest, params *SealKeysParams) ([]byte, error) {
primaryKey = params.PrimaryKey
}

err := withSingleTPMConnection(func(tpm *sb_tpm2.Connection) error {
pcrProfile, err := buildPCRProtectionProfile(params.ModelParams)
if err != nil {
return err
}

pcrHandle := params.PCRPolicyCounterHandle
logger.Noticef("sealing with PCR handle %#x", pcrHandle)

for _, key := range keys {
creationParams := &sb_tpm2.ProtectKeyParams{
PCRProfile: pcrProfile,
// TODO: add roles
PCRPolicyCounterHandle: tpm2.Handle(pcrHandle),
PrimaryKey: primaryKey,
}
protectedKey, primaryKeyOut, unlockKey, err := newTPMProtectedKey(tpm, creationParams, params.VolumesAuth)
if primaryKey == nil {
primaryKey = primaryKeyOut
}
if err != nil {
return err
}
if err := key.BootstrappedContainer.AddKey(key.SlotName, unlockKey); err != nil {
return err
}
pcrProfile, err := buildPCRProtectionProfile(params.ModelParams)
if err != nil {
return nil, err
}

keyWriter, err := key.getWriter()
if err != nil {
return err
}
pcrHandle := params.PCRPolicyCounterHandle
logger.Noticef("sealing with PCR handle %#x", pcrHandle)

if err := protectedKey.WriteAtomic(keyWriter); err != nil {
return err
}
for _, key := range keys {
creationParams := &sb_tpm2.ProtectKeyParams{
PCRProfile: pcrProfile,
// TODO: add roles
PCRPolicyCounterHandle: tpm2.Handle(pcrHandle),
PrimaryKey: primaryKey,
}
protectedKey, primaryKeyOut, unlockKey, err := newTPMProtectedKey(creationParams, params.VolumesAuth)
if primaryKey == nil {
primaryKey = primaryKeyOut
}
if err != nil {
return nil, err
}
if err := key.BootstrappedContainer.AddKey(key.SlotName, unlockKey); err != nil {
return nil, err
}

keyWriter, err := key.getWriter()
if err != nil {
return nil, err
}

if primaryKey != nil && params.TPMPolicyAuthKeyFile != "" {
if err := osutil.AtomicWriteFile(params.TPMPolicyAuthKeyFile, primaryKey, 0600, 0); err != nil {
return fmt.Errorf("cannot write the policy auth key file: %v", err)
}
if err := protectedKey.WriteAtomic(keyWriter); err != nil {
return nil, err
}

return nil
})
}

if primaryKey != nil && params.TPMPolicyAuthKeyFile != "" {
if err := osutil.AtomicWriteFile(params.TPMPolicyAuthKeyFile, primaryKey, 0600, 0); err != nil {
return nil, fmt.Errorf("cannot write the policy auth key file: %v", err)
}
}

return primaryKey, err
return primaryKey, nil
}

// ResealKeys updates the PCR protection policy for the sealed encryption keys
Expand Down

0 comments on commit d766ab6

Please sign in to comment.