From bf11432f64df805c7681cc1a702b4734b24b3b4d Mon Sep 17 00:00:00 2001 From: Valentin David Date: Thu, 3 Oct 2024 15:41:43 +0200 Subject: [PATCH] secboot: factor code for encrypted disk activation This factors and simplifies the TPM and FDE Hook code together. This does not yet factor the key file base one. --- secboot/secboot_hooks.go | 97 ----------------------- secboot/secboot_sb.go | 54 +++++++++++-- secboot/secboot_sb_test.go | 152 +++++++++++++++++-------------------- secboot/secboot_tpm.go | 48 +----------- 4 files changed, 121 insertions(+), 230 deletions(-) diff --git a/secboot/secboot_hooks.go b/secboot/secboot_hooks.go index 256668a379b..fa018b9ee91 100644 --- a/secboot/secboot_hooks.go +++ b/secboot/secboot_hooks.go @@ -31,7 +31,6 @@ import ( sb "github.com/snapcore/secboot" sb_scope "github.com/snapcore/secboot/bootscope" sb_hooks "github.com/snapcore/secboot/hooks" - "golang.org/x/xerrors" "github.com/snapcore/snapd/kernel/fde" "github.com/snapcore/snapd/logger" @@ -136,102 +135,6 @@ func isV1EncryptedKeyFile(p string) bool { return bytes.HasPrefix(buf, v1KeyPrefix) } -// We have to deal with the following cases: -// 1. Key created with v1 data-format on disk (raw encrypted key), v1 hook reads the data -// 2. Key created with v2 data-format on disk (json), v1 hook created the data (no handle) and reads the data (hook output not json but raw binary data) -// 3. Key created with v1 data-format on disk (raw), v2 hook -// 4. Key created with v2 data-format on disk (json), v2 hook [easy] -func unlockVolumeUsingSealedKeyFDERevealKey(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName string, opts *UnlockVolumeUsingSealedKeyOptions) (UnlockResult, error) { - // deal with v1 keys - if isV1EncryptedKeyFile(sealedEncryptionKeyFile) { - return unlockVolumeUsingSealedKeyFDERevealKeyV1(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName) - } - return unlockVolumeUsingSealedKeyFDERevealKeyV2(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) -} - -func unlockVolumeUsingSealedKeyFDERevealKeyV1(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName string) (UnlockResult, error) { - res := UnlockResult{IsEncrypted: true, PartDevice: sourceDevice} - - sealedKey, err := os.ReadFile(sealedEncryptionKeyFile) - if err != nil { - return res, fmt.Errorf("cannot read sealed key file: %v", err) - } - - p := fde.RevealParams{ - SealedKey: sealedKey, - } - output, err := fde.Reveal(&p) - if err != nil { - return res, err - } - - // the output of fde-reveal-key is the unsealed key - unsealedKey := output - if err := unlockEncryptedPartitionWithKey(mapperName, sourceDevice, unsealedKey); err != nil { - return res, fmt.Errorf("cannot unlock encrypted partition: %v", err) - } - res.FsDevice = targetDevice - res.UnlockMethod = UnlockedWithSealedKey - return res, nil -} - -func unlockVolumeUsingSealedKeyFDERevealKeyV2(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName string, opts *UnlockVolumeUsingSealedKeyOptions) (res UnlockResult, err error) { - res = UnlockResult{IsEncrypted: true, PartDevice: sourceDevice} - - f, err := sb.NewFileKeyDataReader(sealedEncryptionKeyFile) - if err != nil { - return res, err - } - keyData, err := sb.ReadKeyData(f) - if err != nil { - fmt := "cannot read key data: %w" - return res, xerrors.Errorf(fmt, err) - } - - model, err := opts.WhichModel() - if err != nil { - return res, fmt.Errorf("cannot retrieve which model to unlock for: %v", err) - } - - // the output of fde-reveal-key is the unsealed key - options := activateVolOpts(opts.AllowRecoveryKey) - // FIXME: consider setting it in activateVolOpts if we keep - // this function separate from the tpm one for key data in - // files. Otherwise we should only set it if we provide key - // data generation 1. - options.Model = model - - sbSetModel(model) - // This does not seem to work: - //defer sbSetModel(nil) - // TODO: set boot mode - //sbSetBootMode("run") - //defer sbSetBootMode("") - sbSetKeyRevealer(&keyRevealerV3{}) - defer sbSetKeyRevealer(nil) - - authRequestor, err := newAuthRequestor() - if err != nil { - return res, fmt.Errorf("internal error: cannot build an auth requestor: %v", err) - } - - err = sbActivateVolumeWithKeyData(mapperName, sourceDevice, authRequestor, options, keyData) - if err == sb.ErrRecoveryKeyUsed { - logger.Noticef("successfully activated encrypted device %q using a fallback activation method", sourceDevice) - res.FsDevice = targetDevice - res.UnlockMethod = UnlockedWithRecoveryKey - return res, nil - } - if err != nil { - return res, fmt.Errorf("cannot unlock encrypted partition: %v", err) - } - - logger.Noticef("successfully activated encrypted device %q using FDE kernel hooks", sourceDevice) - res.FsDevice = targetDevice - res.UnlockMethod = UnlockedWithSealedKey - return res, nil -} - type fdeHookV2DataHandler struct{} func (fh *fdeHookV2DataHandler) RecoverKeys(data *sb.PlatformKeyData, encryptedPayload []byte) ([]byte, error) { diff --git a/secboot/secboot_sb.go b/secboot/secboot_sb.go index d09c4e56fdf..d4ccf7509d5 100644 --- a/secboot/secboot_sb.go +++ b/secboot/secboot_sb.go @@ -120,13 +120,57 @@ func UnlockVolumeUsingSealedKeyIfEncrypted(disk disks.Disk, name string, sealedE sourceDevice := fmt.Sprintf("/dev/disk/by-uuid/%s", part.FilesystemUUID) targetDevice := filepath.Join("/dev/mapper", mapperName) - if fdeHasRevealKey() { - res, err = unlockVolumeUsingSealedKeyFDERevealKey(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) + res.PartDevice = partDevice + + keyData, _, err := readKeyFile(sealedEncryptionKeyFile) + if err != nil { + return res, err + } + + var keys []*sb.KeyData + + if keyData != nil { + keys = append(keys, keyData) + } + + if opts.WhichModel != nil { + model, err := opts.WhichModel() + if err != nil { + return res, fmt.Errorf("cannot retrieve which model to unlock for: %v", err) + } + sbSetModel(model) + // This does not seem to work: + //defer sbSetModel(nil) + } + // TODO: set boot mode + //sbSetBootMode("run") + //defer sbSetBootMode("") + sbSetKeyRevealer(&keyRevealerV3{}) + defer sbSetKeyRevealer(nil) + + options := activateVolOpts(opts.AllowRecoveryKey) + // TODO: remove this + options.Model = sb.SkipSnapModelCheck + authRequestor, err := newAuthRequestor() + if err != nil { + res.UnlockMethod = NotUnlocked + return res, fmt.Errorf("internal error: cannot build an auth requestor: %v", err) + } + + err = sbActivateVolumeWithKeyData(mapperName, sourceDevice, authRequestor, options, keys...) + if err == sb.ErrRecoveryKeyUsed { + logger.Noticef("successfully activated encrypted device %q using a fallback activation method", sourceDevice) + res.UnlockMethod = UnlockedWithRecoveryKey + } else if err != nil { + res.UnlockMethod = NotUnlocked + return res, fmt.Errorf("cannot activate encrypted device %q: %v", sourceDevice, err) } else { - res, err = unlockVolumeUsingSealedKeyTPM(name, sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) + logger.Noticef("successfully activated encrypted device %q with TPM", sourceDevice) + res.UnlockMethod = UnlockedWithSealedKey } - res.PartDevice = partDevice - return res, err + + res.FsDevice = targetDevice + return res, nil } // UnlockEncryptedVolumeUsingKey unlocks an existing volume using the provided key. diff --git a/secboot/secboot_sb_test.go b/secboot/secboot_sb_test.go index 7f555951d57..6c704ca89ac 100644 --- a/secboot/secboot_sb_test.go +++ b/secboot/secboot_sb_test.go @@ -451,12 +451,10 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { } for idx, tc := range []struct { - tpmErr error tpmEnabled bool // TPM storage and endorsement hierarchies disabled, only relevant if TPM available hasEncdev bool // an encrypted device exists rkAllow bool // allow recovery key activation rkErr error // recovery key unlock error, only relevant if TPM not available - activated bool // the activation operation succeeded activateErr error // the activation error uuidFailure bool // failure to get valid uuid err string @@ -468,32 +466,32 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { { // happy case with tpm and encrypted device tpmEnabled: true, hasEncdev: true, - activated: true, disk: mockDiskWithEncDev, expUnlockMethod: secboot.UnlockedWithSealedKey, }, { // happy case with tpm and old sealed key tpmEnabled: true, hasEncdev: true, - activated: true, disk: mockDiskWithEncDev, expUnlockMethod: secboot.UnlockedWithSealedKey, oldKeyFormat: true, }, { // encrypted device: failure to generate uuid based target device name - tpmEnabled: true, hasEncdev: true, activated: true, uuidFailure: true, + tpmEnabled: true, hasEncdev: true, uuidFailure: true, disk: mockDiskWithEncDev, err: "mocked uuid error", }, { // device activation fails tpmEnabled: true, hasEncdev: true, - err: "cannot activate encrypted device .*: activation error", - disk: mockDiskWithEncDev, + activateErr: fmt.Errorf("activation error"), + err: "cannot activate encrypted device .*: activation error", + disk: mockDiskWithEncDev, }, { // device activation fails tpmEnabled: true, hasEncdev: true, - err: "cannot activate encrypted device .*: activation error", - disk: mockDiskWithEncDev, + activateErr: fmt.Errorf("activation error"), + err: "cannot activate encrypted device .*: activation error", + disk: mockDiskWithEncDev, }, { // happy case without encrypted device tpmEnabled: true, @@ -501,19 +499,10 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { }, { // happy case with tpm and encrypted device, activation // with recovery key - tpmEnabled: true, hasEncdev: true, activated: true, + tpmEnabled: true, hasEncdev: true, activateErr: sb.ErrRecoveryKeyUsed, disk: mockDiskWithEncDev, expUnlockMethod: secboot.UnlockedWithRecoveryKey, - }, { - // tpm error, no encrypted device - tpmErr: errors.New("tpm error"), - disk: mockDiskWithUnencDev, - }, { - // tpm error, has encrypted device - tpmErr: errors.New("tpm error"), hasEncdev: true, - err: `cannot unlock encrypted device "name": tpm error`, - disk: mockDiskWithEncDev, }, { // tpm disabled, no encrypted device disk: mockDiskWithUnencDev, @@ -521,36 +510,16 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { // tpm disabled, has encrypted device, unlocked using the recovery key hasEncdev: true, rkAllow: true, + activateErr: sb.ErrRecoveryKeyUsed, disk: mockDiskWithEncDev, expUnlockMethod: secboot.UnlockedWithRecoveryKey, }, { // tpm disabled, has encrypted device, recovery key unlocking fails hasEncdev: true, rkErr: errors.New("cannot unlock with recovery key"), - rkAllow: true, - disk: mockDiskWithEncDev, - err: `cannot unlock encrypted device "/dev/disk/by-uuid/enc-dev-uuid": cannot unlock with recovery key`, - }, { - // no tpm, has encrypted device, unlocked using the recovery key - tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, - rkAllow: true, - disk: mockDiskWithEncDev, - expUnlockMethod: secboot.UnlockedWithRecoveryKey, - }, { - // no tpm, has encrypted device, unlocking with recovery key not allowed - tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, - disk: mockDiskWithEncDev, - err: `cannot activate encrypted device "/dev/disk/by-uuid/enc-dev-uuid": activation error`, - }, { - // no tpm, has encrypted device, recovery key unlocking fails - rkErr: errors.New("cannot unlock with recovery key"), - tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, - rkAllow: true, - disk: mockDiskWithEncDev, - err: `cannot unlock encrypted device "/dev/disk/by-uuid/enc-dev-uuid": cannot unlock with recovery key`, - }, { - // no tpm, no encrypted device - tpmErr: sb_tpm2.ErrNoTPM2Device, - disk: mockDiskWithUnencDev, + rkAllow: true, + activateErr: fmt.Errorf("some error"), + disk: mockDiskWithEncDev, + err: `cannot activate encrypted device "/dev/disk/by-uuid/enc-dev-uuid": some error`, }, { // no disks at all disk: mockDiskWithoutAnyDev, @@ -572,9 +541,6 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { }) defer restore() - _, restoreConnect := mockSbTPMConnection(c, tc.tpmErr) - defer restoreConnect() - restore = secboot.MockIsTPMEnabled(func(tpm *sb_tpm2.Connection) bool { return tc.tpmEnabled }) @@ -699,20 +665,14 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { Model: sb.SkipSnapModelCheck, }) } - if !tc.activated && tc.activateErr == nil { - return errors.New("activation error") - } return tc.activateErr }) defer restore() restore = secboot.MockSbActivateVolumeWithRecoveryKey(func(name, device string, authReq sb.AuthRequestor, options *sb.ActivateVolumeOptions) error { - if !tc.rkAllow { - c.Fatalf("unexpected attempt to activate with recovery key") - return fmt.Errorf("unexpected call") - } - return tc.rkErr + c.Errorf("unexpected call") + return fmt.Errorf("unexpected call") }) defer restore() @@ -1497,7 +1457,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyErr( }, } _, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, mockSealedKeyFile, opts) - c.Assert(err, ErrorMatches, `cannot unlock encrypted partition: cannot perform action because of an unexpected error: cannot run \["fde-reveal-key"\]: helper error`) + c.Assert(err, ErrorMatches, `cannot activate encrypted device "/dev/disk/by-uuid/enc-dev-uuid": cannot perform action because of an unexpected error: cannot run \["fde-reveal-key"\]: helper error`) } // this test that v1 hooks and raw binary v1 created sealedKey files still work @@ -1532,24 +1492,38 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1An }, } - activated := 0 restore = secboot.MockSbActivateVolumeWithKey(func(volumeName, sourceDevicePath string, key []byte, options *sb.ActivateVolumeOptions) error { + c.Errorf("unexpected error") + return fmt.Errorf("unexpected error") + }) + defer restore() + + mockSealedKeyObject, err := sb_tpm2.ReadSealedKeyObjectFromFile(filepath.Join("test-data", "keyfile")) + c.Assert(err, IsNil) + reader, err := sb.NewFileKeyDataReader(filepath.Join("test-data", "keydata")) + c.Assert(err, IsNil) + mockKeyData, err := sb.ReadKeyData(reader) + c.Assert(err, IsNil) + + restore = secboot.MockReadKeyFile(func(keyfile string) (*sb.KeyData, *sb_tpm2.SealedKeyObject, error) { + c.Check(keyfile, Equals, "the-key-file") + return mockKeyData, mockSealedKeyObject, nil + }) + defer restore() + + activated := 0 + restore = secboot.MockSbActivateVolumeWithKeyData(func(volumeName, sourceDevicePath string, authRequestor sb.AuthRequestor, options *sb.ActivateVolumeOptions, keys ...*sb.KeyData) error { activated++ - c.Check(string(key), Equals, "unsealed-key-64-chars-long-when-not-json-to-match-denver-project") + c.Assert(keys, HasLen, 1) + c.Check(keys[0], DeepEquals, mockKeyData) return nil }) defer restore() defaultDevice := "device-name" - // note that we write a v1 created keyfile here, i.e. it's a raw - // disk-key without any json - mockSealedKeyFile := filepath.Join(c.MkDir(), "keyfile") - sealedKeyContent := []byte("USK$sealed-key-not-json-to-match-denver-project") - err := os.WriteFile(mockSealedKeyFile, sealedKeyContent, 0600) - c.Assert(err, IsNil) opts := &secboot.UnlockVolumeUsingSealedKeyOptions{} - res, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, mockSealedKeyFile, opts) + res, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, "the-key-file", opts) c.Assert(err, IsNil) c.Check(res, DeepEquals, secboot.UnlockResult{ UnlockMethod: secboot.UnlockedWithSealedKey, @@ -1558,9 +1532,8 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1An FsDevice: "/dev/mapper/device-name-random-uuid-for-test", }) c.Check(activated, Equals, 1) - c.Check(reqs, HasLen, 1) - c.Check(reqs[0].Op, Equals, "reveal") - c.Check(reqs[0].SealedKey, DeepEquals, sealedKeyContent) + // FIXME: maybe we should remove this test + c.Check(reqs, HasLen, 0) } func (s *secbootSuite) TestLockSealedKeysCallsFdeReveal(c *C) { @@ -1800,7 +1773,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV2Ac }, } res, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, mockSealedKeyFile, opts) - c.Assert(err, ErrorMatches, `cannot unlock encrypted partition: some activation error`) + c.Assert(err, ErrorMatches, `cannot activate encrypted device "/dev/disk/by-uuid/enc-dev-uuid": some activation error`) c.Check(res, DeepEquals, secboot.UnlockResult{ IsEncrypted: true, PartDevice: "/dev/disk/by-partuuid/enc-dev-partuuid", @@ -1976,24 +1949,39 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1(c }, } - mockEncryptedDiskKey := []byte("USK$encrypted-key-no-json-to-match-denver-project") - activated := 0 + mockSealedKeyObject, err := sb_tpm2.ReadSealedKeyObjectFromFile(filepath.Join("test-data", "keyfile")) + c.Assert(err, IsNil) + reader, err := sb.NewFileKeyDataReader(filepath.Join("test-data", "keydata")) + c.Assert(err, IsNil) + mockKeyData, err := sb.ReadKeyData(reader) + c.Assert(err, IsNil) + + restore = secboot.MockReadKeyFile(func(keyfile string) (*sb.KeyData, *sb_tpm2.SealedKeyObject, error) { + c.Check(keyfile, Equals, "the-key-file") + return mockKeyData, mockSealedKeyObject, nil + }) + defer restore() + restore = secboot.MockSbActivateVolumeWithKey(func(volumeName, sourceDevicePath string, key []byte, options *sb.ActivateVolumeOptions) error { + c.Errorf("unexpected calls") + return fmt.Errorf("unexpected calls") + }) + + defer restore() + + activated := 0 + restore = secboot.MockSbActivateVolumeWithKeyData(func(volumeName, sourceDevicePath string, authRequestor sb.AuthRequestor, options *sb.ActivateVolumeOptions, keys ...*sb.KeyData) error { activated++ - c.Check(key, DeepEquals, mockDiskKey) + c.Assert(keys, HasLen, 1) + c.Check(keys[0], DeepEquals, mockKeyData) return nil }) defer restore() defaultDevice := "device-name" - // note that we write a v1 created keyfile here, i.e. it's a raw - // disk-key without any json - mockSealedKeyFile := filepath.Join(c.MkDir(), "keyfile") - err := os.WriteFile(mockSealedKeyFile, mockEncryptedDiskKey, 0600) - c.Assert(err, IsNil) opts := &secboot.UnlockVolumeUsingSealedKeyOptions{} - res, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, mockSealedKeyFile, opts) + res, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, "the-key-file", opts) c.Assert(err, IsNil) c.Check(res, DeepEquals, secboot.UnlockResult{ UnlockMethod: secboot.UnlockedWithSealedKey, @@ -2002,10 +1990,8 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1(c FsDevice: "/dev/mapper/device-name-random-uuid-for-test", }) c.Check(activated, Equals, 1) - c.Check(reqs, HasLen, 1) - c.Check(reqs[0].Op, Equals, "reveal") - c.Check(reqs[0].SealedKey, DeepEquals, mockEncryptedDiskKey) - c.Check(reqs[0].Handle, IsNil) + // Maybe this test is superfluous + c.Check(reqs, HasLen, 0) } func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyBadJSONv2(c *C) { @@ -2059,7 +2045,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyBadJ } _, err := secboot.UnlockVolumeUsingSealedKeyIfEncrypted(mockDiskWithEncDev, defaultDevice, mockSealedKeyFile, opts) - c.Check(err, ErrorMatches, `cannot unlock encrypted partition: invalid key data:.*`) + c.Check(err, ErrorMatches, `cannot activate encrypted device \".*\": invalid key data: cannot unmarshal cleartext key payload: EOF`) } func (s *secbootSuite) TestPCRHandleOfSealedKey(c *C) { diff --git a/secboot/secboot_tpm.go b/secboot/secboot_tpm.go index 398a7a8de2f..c89cc4cc59d 100644 --- a/secboot/secboot_tpm.go +++ b/secboot/secboot_tpm.go @@ -217,51 +217,6 @@ func lockTPMSealedKeys() error { return sbBlockPCRProtectionPolicies(tpm, []int{initramfsPCR}) } -func unlockVolumeUsingSealedKeyTPM(name, sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName string, opts *UnlockVolumeUsingSealedKeyOptions) (UnlockResult, error) { - // TODO:UC20: use sb.SecureConnectToDefaultTPM() if we decide there's benefit in doing that or - // we have a hard requirement for a valid EK cert chain for every boot (ie, panic - // if there isn't one). But we can't do that as long as we need to download - // intermediate certs from the manufacturer. - - res := UnlockResult{IsEncrypted: true, PartDevice: sourceDevice} - tpmDeviceAvailable := false - // Obtain a TPM connection. - if tpm, tpmErr := sbConnectToDefaultTPM(); tpmErr != nil { - if !xerrors.Is(tpmErr, sb_tpm2.ErrNoTPM2Device) { - return res, fmt.Errorf("cannot unlock encrypted device %q: %v", name, tpmErr) - } - logger.Noticef("cannot open TPM connection: %v", tpmErr) - } else { - // Also check if the TPM device is enabled. The platform firmware may disable the storage - // and endorsement hierarchies, but the device will remain visible to the operating system. - tpmDeviceAvailable = isTPMEnabled(tpm) - // later during ActivateVolumeWithKeyData secboot will - // open the TPM again, close it as it can't be opened - // multiple times and also we are done using it here - tpm.Close() - } - - // if we don't have a tpm, and we allow using a recovery key, do that - // directly - if !tpmDeviceAvailable && opts.AllowRecoveryKey { - if err := UnlockEncryptedVolumeWithRecoveryKey(mapperName, sourceDevice); err != nil { - return res, err - } - res.FsDevice = targetDevice - res.UnlockMethod = UnlockedWithRecoveryKey - return res, nil - } - - // otherwise we have a tpm and we should use the sealed key first, but - // this method will fallback to using the recovery key if enabled - method, err := unlockEncryptedPartitionWithSealedKey(mapperName, sourceDevice, sealedEncryptionKeyFile, opts.AllowRecoveryKey) - res.UnlockMethod = method - if err == nil { - res.FsDevice = targetDevice - } - return res, err -} - func activateVolOpts(allowRecoveryKey bool) *sb.ActivateVolumeOptions { options := sb.ActivateVolumeOptions{ PassphraseTries: 1, @@ -286,6 +241,9 @@ func newAuthRequestor() (sb.AuthRequestor, error) { // TODO: consider moving this to secboot func readKeyFileImpl(keyfile string) (*sb.KeyData, *sb_tpm2.SealedKeyObject, error) { f, err := os.Open(keyfile) + if os.IsNotExist(err) { + return nil, nil, err + } if err != nil { return nil, nil, err }