diff options
| author | Eric Biggers <ebiggers@google.com> | 2021-12-20 11:14:08 -0600 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2021-12-21 13:00:58 -0600 |
| commit | dce50d2a55525ec1309fd60a3c240d243d5f7145 (patch) | |
| tree | 2fbe4381eae0b234f82671a7d62998e063fa3c8b /keyring/user_keyring.go | |
| parent | 9a8ce15408edae0c92128fd36f50dafa81013266 (diff) | |
[BROKEN] pam_fscrypt: save unlocked protector keys in root user keyring
Diffstat (limited to 'keyring/user_keyring.go')
| -rw-r--r-- | keyring/user_keyring.go | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/keyring/user_keyring.go b/keyring/user_keyring.go index 0ea4689..416872f 100644 --- a/keyring/user_keyring.go +++ b/keyring/user_keyring.go @@ -32,6 +32,7 @@ import ( "log" "github.com/google/fscrypt/crypto" + "github.com/google/fscrypt/metadata" "github.com/google/fscrypt/security" "github.com/google/fscrypt/util" ) @@ -181,6 +182,80 @@ func UserKeyringID(targetUser *user.User, checkSession bool) (int, error) { return targetKeyring, nil } +func protectorKeyDescription(user *user.User) string { + return fmt.Sprintf("fscrypt-protector-key.uid.%s", user.Uid) +} + +func SaveProtectorKey(key *crypto.Key, user *user.User) error { + runtime.LockOSThread() // ensure the thread keyring doesn't change + defer runtime.UnlockOSThread() + + keyringID, err := userKeyringIDLookup(0) + if err != nil { + return errors.Wrap(err, "could not find root user keyring") + } + + description := protectorKeyDescription(user) + _, err = unix.AddKey("user", description, key.Data(), keyringID) + if err != nil { + return err + } + log.Printf("saved protector key for %s", user.Username) + return nil +} + +func RestoreProtectorKey(user *user.User) (*crypto.Key, error) { + runtime.LockOSThread() // ensure the thread keyring doesn't change + defer runtime.UnlockOSThread() + + keyringID, err := userKeyringIDLookup(0) + if err != nil { + return nil, errors.Wrap(err, "could not find root user keyring") + } + + description := protectorKeyDescription(user) + keyID, err := unix.KeyctlSearch(keyringID, "user", description, 0) + if err != nil { + return nil, errors.Wrap(err, "could not find saved protector key") + } + + key, err := crypto.NewBlankKey(metadata.InternalKeyLen) + if err != nil { + return nil, err + } + ret, err := unix.KeyctlBuffer(unix.KEYCTL_READ, keyID, key.Data(), key.Len()) + if err != nil { + return nil, errors.Wrap(err, "could not read saved protector key") + } + if ret != metadata.InternalKeyLen { + return nil, errors.New("bad saved protector key") + } + log.Printf("loaded saved protector key for %s", user.Username) + return key, nil +} + +func DeleteSavedProtectorKey(user *user.User) error { + runtime.LockOSThread() // ensure the thread keyring doesn't change + defer runtime.UnlockOSThread() + + keyringID, err := userKeyringIDLookup(0) + if err != nil { + return nil + } + + description := protectorKeyDescription(user) + keyID, err := unix.KeyctlSearch(keyringID, "user", description, 0) + if err != nil { + return nil + } + + if _, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, keyID, keyringID, 0, 0); err != nil { + return errors.Wrap(err, "could not delete saved protector key") + } + log.Printf("deleted saved protector key for %s", user.Username) + return nil +} + func userKeyringIDLookup(uid int) (keyringID int, err error) { // Our goals here are to: |