diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 180735bf48eb8e64dc44e98c7510bef8aec4ba3d..90a40717eadabe315be5f3d5d62f9c27e73547e3 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -2372,14 +2372,14 @@ public final class StrictMode { } /** Assume locked until we hear otherwise */ - private static volatile boolean sUserKeyUnlocked = false; + private static volatile boolean sCeStorageUnlocked = false; - private static boolean isUserKeyUnlocked(int userId) { + private static boolean isCeStorageUnlocked(int userId) { final IStorageManager storage = IStorageManager.Stub .asInterface(ServiceManager.getService("mount")); if (storage != null) { try { - return storage.isUserKeyUnlocked(userId); + return storage.isCeStorageUnlocked(userId); } catch (RemoteException ignored) { } } @@ -2392,13 +2392,13 @@ public final class StrictMode { // since any relocking of that user will always result in our // process being killed to release any CE FDs we're holding onto. if (userId == UserHandle.myUserId()) { - if (sUserKeyUnlocked) { + if (sCeStorageUnlocked) { return; - } else if (isUserKeyUnlocked(userId)) { - sUserKeyUnlocked = true; + } else if (isCeStorageUnlocked(userId)) { + sCeStorageUnlocked = true; return; } - } else if (isUserKeyUnlocked(userId)) { + } else if (isCeStorageUnlocked(userId)) { return; } diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index bc52744078ea26f07e44c24169c1c6fa718fc5c5..25b2aa7842f23f2706afd69cd3774dae855449f9 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -134,20 +134,20 @@ interface IStorageManager { @EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS") void setDebugFlags(int flags, int mask) = 60; @EnforcePermission("STORAGE_INTERNAL") - void createUserKey(int userId, int serialNumber, boolean ephemeral) = 61; + void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) = 61; @EnforcePermission("STORAGE_INTERNAL") - void destroyUserKey(int userId) = 62; + void destroyUserStorageKeys(int userId) = 62; @EnforcePermission("STORAGE_INTERNAL") - void unlockUserKey(int userId, int serialNumber, in byte[] secret) = 63; + void unlockCeStorage(int userId, int serialNumber, in byte[] secret) = 63; @EnforcePermission("STORAGE_INTERNAL") - void lockUserKey(int userId) = 64; - boolean isUserKeyUnlocked(int userId) = 65; + void lockCeStorage(int userId) = 64; + boolean isCeStorageUnlocked(int userId) = 65; @EnforcePermission("STORAGE_INTERNAL") void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66; @EnforcePermission("STORAGE_INTERNAL") void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67; @EnforcePermission("STORAGE_INTERNAL") - void setUserKeyProtection(int userId, in byte[] secret) = 70; + void setCeStorageProtection(int userId, in byte[] secret) = 70; @EnforcePermission("MOUNT_FORMAT_FILESYSTEMS") void fstrim(int flags, IVoldTaskListener listener) = 72; AppFuseMount mountProxyFileDescriptorBridge() = 73; diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 80dd48825ba7c02ec6f6426fb4f782c882ec5c83..8e72e13051b0986d0756b875709982e7c8a5eb3d 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1580,28 +1580,64 @@ public class StorageManager { DEFAULT_FULL_THRESHOLD_BYTES); } - /** {@hide} */ - public void createUserKey(int userId, int serialNumber, boolean ephemeral) { + /** + * Creates the keys for a user's credential-encrypted (CE) and device-encrypted (DE) storage. + * <p> + * This creates the user's CE key and DE key for internal storage, then adds them to the kernel. + * Then, if the user is not ephemeral, this stores the DE key (encrypted) on flash. (The CE key + * is not stored until {@link IStorageManager#setCeStorageProtection()}.) + * <p> + * This does not create the CE and DE directories themselves. For that, see {@link + * #prepareUserStorage()}. + * <p> + * This is only intended to be called by UserManagerService, as part of creating a user. + * + * @param userId ID of the user + * @param serialNumber serial number of the user + * @param ephemeral whether the user is ephemeral + * @throws RuntimeException on error. The user's keys already existing is considered an error. + * @hide + */ + public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) { try { - mStorageManager.createUserKey(userId, serialNumber, ephemeral); + mStorageManager.createUserStorageKeys(userId, serialNumber, ephemeral); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - /** {@hide} */ - public void destroyUserKey(int userId) { + /** + * Destroys the keys for a user's credential-encrypted (CE) and device-encrypted (DE) storage. + * <p> + * This evicts the keys from the kernel (if present), which "locks" the corresponding + * directories. Then, this deletes the encrypted keys from flash. This operates on all the + * user's CE and DE keys, for both internal and adoptable storage. + * <p> + * This does not destroy the CE and DE directories themselves. For that, see {@link + * #destroyUserStorage()}. + * <p> + * This is only intended to be called by UserManagerService, as part of removing a user. + * + * @param userId ID of the user + * @throws RuntimeException on error. On error, as many things as possible are still destroyed. + * @hide + */ + public void destroyUserStorageKeys(int userId) { try { - mStorageManager.destroyUserKey(userId); + mStorageManager.destroyUserStorageKeys(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - /** {@hide} */ - public void lockUserKey(int userId) { + /** + * Locks the user's credential-encrypted (CE) storage. + * + * @hide + */ + public void lockCeStorage(int userId) { try { - mStorageManager.lockUserKey(userId); + mStorageManager.lockCeStorage(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1628,17 +1664,26 @@ public class StorageManager { /** {@hide} */ @TestApi public static boolean isUserKeyUnlocked(int userId) { + return isCeStorageUnlocked(userId); + } + + /** + * Returns true if the user's credential-encrypted (CE) storage is unlocked. + * + * @hide + */ + public static boolean isCeStorageUnlocked(int userId) { if (sStorageManager == null) { sStorageManager = IStorageManager.Stub .asInterface(ServiceManager.getService("mount")); } if (sStorageManager == null) { - Slog.w(TAG, "Early during boot, assuming locked"); + Slog.w(TAG, "Early during boot, assuming CE storage is locked"); return false; } final long token = Binder.clearCallingIdentity(); try { - return sStorageManager.isUserKeyUnlocked(userId); + return sStorageManager.isCeStorageUnlocked(userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 493b30b3f4b59122b2ff600ead6e9f61db2a5ef1..61584b727aa7da2b96f61542e3e24abe63736522 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2984,7 +2984,7 @@ class StorageManagerService extends IStorageManager.Stub // We need all the users unlocked to move their primary storage users = mContext.getSystemService(UserManager.class).getUsers(); for (UserInfo user : users) { - if (StorageManager.isFileEncrypted() && !isUserKeyUnlocked(user.id)) { + if (StorageManager.isFileEncrypted() && !isCeStorageUnlocked(user.id)) { Slog.w(TAG, "Failing move due to locked user " + user.id); onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER); return; @@ -3208,12 +3208,12 @@ class StorageManagerService extends IStorageManager.Stub @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void createUserKey(int userId, int serialNumber, boolean ephemeral) { + public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) { - super.createUserKey_enforcePermission(); + super.createUserStorageKeys_enforcePermission(); try { - mVold.createUserKey(userId, serialNumber, ephemeral); + mVold.createUserStorageKeys(userId, serialNumber, ephemeral); // Since the user's CE key was just created, the user's CE storage is now unlocked. synchronized (mLock) { mCeUnlockedUsers.append(userId); @@ -3225,12 +3225,12 @@ class StorageManagerService extends IStorageManager.Stub @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void destroyUserKey(int userId) { + public void destroyUserStorageKeys(int userId) { - super.destroyUserKey_enforcePermission(); + super.destroyUserStorageKeys_enforcePermission(); try { - mVold.destroyUserKey(userId); + mVold.destroyUserStorageKeys(userId); // Since the user's CE key was just destroyed, the user's CE storage is now locked. synchronized (mLock) { mCeUnlockedUsers.remove(userId); @@ -3243,21 +3243,22 @@ class StorageManagerService extends IStorageManager.Stub /* Only for use by LockSettingsService */ @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void setUserKeyProtection(@UserIdInt int userId, byte[] secret) throws RemoteException { - super.setUserKeyProtection_enforcePermission(); + public void setCeStorageProtection(@UserIdInt int userId, byte[] secret) + throws RemoteException { + super.setCeStorageProtection_enforcePermission(); - mVold.setUserKeyProtection(userId, HexDump.toHexString(secret)); + mVold.setCeStorageProtection(userId, HexDump.toHexString(secret)); } /* Only for use by LockSettingsService */ @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void unlockUserKey(@UserIdInt int userId, int serialNumber, byte[] secret) - throws RemoteException { - super.unlockUserKey_enforcePermission(); + public void unlockCeStorage(@UserIdInt int userId, int serialNumber, byte[] secret) + throws RemoteException { + super.unlockCeStorage_enforcePermission(); if (StorageManager.isFileEncrypted()) { - mVold.unlockUserKey(userId, serialNumber, HexDump.toHexString(secret)); + mVold.unlockCeStorage(userId, serialNumber, HexDump.toHexString(secret)); } synchronized (mLock) { mCeUnlockedUsers.append(userId); @@ -3266,23 +3267,22 @@ class StorageManagerService extends IStorageManager.Stub @android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL) @Override - public void lockUserKey(int userId) { - // Do not lock user 0 data for headless system user - super.lockUserKey_enforcePermission(); + public void lockCeStorage(int userId) { + super.lockCeStorage_enforcePermission(); + // Never lock the CE storage of a headless system user. if (userId == UserHandle.USER_SYSTEM && UserManager.isHeadlessSystemUserMode()) { throw new IllegalArgumentException("Headless system user data cannot be locked.."); } - - if (!isUserKeyUnlocked(userId)) { + if (!isCeStorageUnlocked(userId)) { Slog.d(TAG, "User " + userId + "'s CE storage is already locked"); return; } try { - mVold.lockUserKey(userId); + mVold.lockCeStorage(userId); } catch (Exception e) { Slog.wtf(TAG, e); return; @@ -3294,7 +3294,7 @@ class StorageManagerService extends IStorageManager.Stub } @Override - public boolean isUserKeyUnlocked(int userId) { + public boolean isCeStorageUnlocked(int userId) { synchronized (mLock) { return mCeUnlockedUsers.contains(userId); } @@ -3681,8 +3681,8 @@ class StorageManagerService extends IStorageManager.Stub final int userId = UserHandle.getUserId(callingUid); final String propertyName = "sys.user." + userId + ".ce_available"; - // Ignore requests to create directories while storage is locked - if (!isUserKeyUnlocked(userId)) { + // Ignore requests to create directories while CE storage is locked + if (!isCeStorageUnlocked(userId)) { throw new IllegalStateException("Failed to prepare " + appPath); } @@ -3808,15 +3808,15 @@ class StorageManagerService extends IStorageManager.Stub final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM); final boolean userIsDemo; - final boolean userKeyUnlocked; final boolean storagePermission; + final boolean ceStorageUnlocked; final long token = Binder.clearCallingIdentity(); try { userIsDemo = LocalServices.getService(UserManagerInternal.class) .getUserInfo(userId).isDemo(); storagePermission = mStorageManagerInternal.hasExternalStorage(callingUid, callingPackage); - userKeyUnlocked = isUserKeyUnlocked(userId); + ceStorageUnlocked = isCeStorageUnlocked(userId); } finally { Binder.restoreCallingIdentity(token); } @@ -3876,7 +3876,7 @@ class StorageManagerService extends IStorageManager.Stub } else if (!systemUserUnlocked) { reportUnmounted = true; Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked"); - } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) { + } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !ceStorageUnlocked) { reportUnmounted = true; Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked"); } else if (!storagePermission && !realState) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e6df1d91861a57d879728387b8bf94dc80a67cd1..e74371e6a66b2bba455e7bc3842219aed3b8928a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2249,7 +2249,7 @@ public class ActivityManagerService extends IActivityManager.Stub return; } // TODO(b/148767783): should we check all profiles under user0? - UserspaceRebootLogger.logEventAsync(StorageManager.isUserKeyUnlocked(userId), + UserspaceRebootLogger.logEventAsync(StorageManager.isCeStorageUnlocked(userId), BackgroundThread.getExecutor()); } @@ -4564,7 +4564,7 @@ public class ActivityManagerService extends IActivityManager.Stub // We carefully use the same state that PackageManager uses for // filtering, since we use this flag to decide if we need to install // providers when user is unlocked later - app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId)); + app.setUnlocked(StorageManager.isCeStorageUnlocked(app.userId)); } boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 76a994ec63e901dee3f847c4d1fd7e6670e79850..6eb2961fcf869b6f28788ab25483d410e3f5da79 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -639,8 +639,8 @@ class UserController implements Handler.Callback { mInjector.getUserJourneyLogger() .logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_UNLOCKING_USER, EVENT_STATE_BEGIN); - // If the user key hasn't been unlocked yet, we cannot proceed. - if (!StorageManager.isUserKeyUnlocked(userId)) return false; + // If the user's CE storage hasn't been unlocked yet, we cannot proceed. + if (!StorageManager.isCeStorageUnlocked(userId)) return false; synchronized (mLock) { // Do not proceed if unexpected state or a stale user if (mStartedUsers.get(userId) != uss || uss.state != STATE_RUNNING_LOCKED) { @@ -655,8 +655,8 @@ class UserController implements Handler.Callback { // Call onBeforeUnlockUser on a worker thread that allows disk I/O FgThread.getHandler().post(() -> { - if (!StorageManager.isUserKeyUnlocked(userId)) { - Slogf.w(TAG, "User key got locked unexpectedly, leaving user locked."); + if (!StorageManager.isCeStorageUnlocked(userId)) { + Slogf.w(TAG, "User's CE storage got locked unexpectedly, leaving user locked."); return; } @@ -690,8 +690,8 @@ class UserController implements Handler.Callback { private void finishUserUnlocked(final UserState uss) { final int userId = uss.mHandle.getIdentifier(); EventLog.writeEvent(EventLogTags.UC_FINISH_USER_UNLOCKED, userId); - // Only keep marching forward if user is actually unlocked - if (!StorageManager.isUserKeyUnlocked(userId)) return; + // Only keep marching forward if the user's CE storage is unlocked. + if (!StorageManager.isCeStorageUnlocked(userId)) return; synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; @@ -777,8 +777,8 @@ class UserController implements Handler.Callback { if (userInfo == null) { return; } - // Only keep marching forward if user is actually unlocked - if (!StorageManager.isUserKeyUnlocked(userId)) return; + // Only keep marching forward if the user's CE storage is unlocked. + if (!StorageManager.isCeStorageUnlocked(userId)) return; // Remember that we logged in mInjector.getUserManager().onUserLoggedIn(userId); @@ -1256,7 +1256,7 @@ class UserController implements Handler.Callback { } try { Slogf.i(TAG, "Locking CE storage for user #" + userId); - mInjector.getStorageManager().lockUserKey(userId); + mInjector.getStorageManager().lockCeStorage(userId); } catch (RemoteException re) { throw re.rethrowAsRuntimeException(); } @@ -1874,8 +1874,8 @@ class UserController implements Handler.Callback { } UserState uss; - if (!StorageManager.isUserKeyUnlocked(userId)) { - // We always want to try to unlock the user key, even if the user is not started yet. + if (!StorageManager.isCeStorageUnlocked(userId)) { + // We always want to try to unlock CE storage, even if the user is not started yet. mLockPatternUtils.unlockUserKeyIfUnsecured(userId); } synchronized (mLock) { @@ -2662,10 +2662,10 @@ class UserController implements Handler.Callback { case UserState.STATE_RUNNING_UNLOCKING: case UserState.STATE_RUNNING_UNLOCKED: return true; - // In the stopping/shutdown state return unlock state of the user key + // In the stopping/shutdown state, return unlock state of the user's CE storage. case UserState.STATE_STOPPING: case UserState.STATE_SHUTDOWN: - return StorageManager.isUserKeyUnlocked(userId); + return StorageManager.isCeStorageUnlocked(userId); default: return false; } @@ -2674,10 +2674,10 @@ class UserController implements Handler.Callback { switch (state.state) { case UserState.STATE_RUNNING_UNLOCKED: return true; - // In the stopping/shutdown state return unlock state of the user key + // In the stopping/shutdown state, return unlock state of the user's CE storage. case UserState.STATE_STOPPING: case UserState.STATE_SHUTDOWN: - return StorageManager.isUserKeyUnlocked(userId); + return StorageManager.isCeStorageUnlocked(userId); default: return false; } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 4ccc554f1fe13c2230f33ea854e83fa1ce01ae43..fa95a348d8d359d5d8b7a2327b0f1e7585832db9 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -694,9 +694,9 @@ public class LockSettingsService extends ILockSettings.Stub { return; } - if (isUserKeyUnlocked(userId)) { - // If storage is not locked, the user will be automatically unlocked so there is - // no need to show the notification. + if (isCeStorageUnlocked(userId)) { + // If the user's CE storage is already unlocked, then the user will be automatically + // unlocked, so there is no need to show the notification. return; } @@ -1027,8 +1027,8 @@ public class LockSettingsService extends ILockSettings.Stub { // they did have an SP then their CE key wasn't encrypted by it. // // If this gets interrupted (e.g. by the device powering off), there shouldn't be a - // problem since this will run again on the next boot, and setUserKeyProtection() is - // okay with the key being already protected by the given secret. + // problem since this will run again on the next boot, and setCeStorageProtection() is + // okay with the CE key being already protected by the given secret. if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { for (UserInfo user : mUserManager.getAliveUsers()) { removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); @@ -1063,7 +1063,7 @@ public class LockSettingsService extends ILockSettings.Stub { Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId); return; } - setUserKeyProtection(userId, result.syntheticPassword); + setCeStorageProtection(userId, result.syntheticPassword); } } @@ -2002,11 +2002,11 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext)); } - private void setUserKeyProtection(@UserIdInt int userId, SyntheticPassword sp) { + private void setCeStorageProtection(@UserIdInt int userId, SyntheticPassword sp) { final byte[] secret = sp.deriveFileBasedEncryptionKey(); final long callingId = Binder.clearCallingIdentity(); try { - mStorageManager.setUserKeyProtection(userId, secret); + mStorageManager.setCeStorageProtection(userId, secret); } catch (RemoteException e) { throw new IllegalStateException("Failed to protect CE key for user " + userId, e); } finally { @@ -2014,11 +2014,11 @@ public class LockSettingsService extends ILockSettings.Stub { } } - private boolean isUserKeyUnlocked(int userId) { + private boolean isCeStorageUnlocked(int userId) { try { - return mStorageManager.isUserKeyUnlocked(userId); + return mStorageManager.isCeStorageUnlocked(userId); } catch (RemoteException e) { - Slog.e(TAG, "failed to check user key locked state", e); + Slog.e(TAG, "Error checking whether CE storage is unlocked", e); return false; } } @@ -2029,8 +2029,8 @@ public class LockSettingsService extends ILockSettings.Stub { * This method doesn't throw exceptions because it is called opportunistically whenever a user * is started. Whether it worked or not can be detected by whether the key got unlocked or not. */ - private void unlockUserKey(@UserIdInt int userId, SyntheticPassword sp) { - if (isUserKeyUnlocked(userId)) { + private void unlockCeStorage(@UserIdInt int userId, SyntheticPassword sp) { + if (isCeStorageUnlocked(userId)) { Slogf.d(TAG, "CE storage for user %d is already unlocked", userId); return; } @@ -2038,7 +2038,7 @@ public class LockSettingsService extends ILockSettings.Stub { final String userType = isUserSecure(userId) ? "secured" : "unsecured"; final byte[] secret = sp.deriveFileBasedEncryptionKey(); try { - mStorageManager.unlockUserKey(userId, userInfo.serialNumber, secret); + mStorageManager.unlockCeStorage(userId, userInfo.serialNumber, secret); Slogf.i(TAG, "Unlocked CE storage for %s user %d", userType, userId); } catch (RemoteException e) { Slogf.wtf(TAG, e, "Failed to unlock CE storage for %s user %d", userType, userId); @@ -2051,8 +2051,10 @@ public class LockSettingsService extends ILockSettings.Stub { public void unlockUserKeyIfUnsecured(@UserIdInt int userId) { checkPasswordReadPermission(); synchronized (mSpManager) { - if (isUserKeyUnlocked(userId)) { + if (isCeStorageUnlocked(userId)) { Slogf.d(TAG, "CE storage for user %d is already unlocked", userId); + // This method actually does more than unlock CE storage. However, if CE storage is + // already unlocked, then the other parts must have already been done too. return; } if (isUserSecure(userId)) { @@ -2069,7 +2071,7 @@ public class LockSettingsService extends ILockSettings.Stub { return; } onSyntheticPasswordUnlocked(userId, result.syntheticPassword); - unlockUserKey(userId, result.syntheticPassword); + unlockCeStorage(userId, result.syntheticPassword); } } @@ -2772,7 +2774,7 @@ public class LockSettingsService extends ILockSettings.Stub { final long protectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(), LockscreenCredential.createNone(), sp, userId); setCurrentLskfBasedProtectorId(protectorId, userId); - setUserKeyProtection(userId, sp); + setCeStorageProtection(userId, sp); onSyntheticPasswordCreated(userId, sp); Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId); return sp; @@ -2833,7 +2835,7 @@ public class LockSettingsService extends ILockSettings.Stub { unlockKeystore(userId, sp); - unlockUserKey(userId, sp); + unlockCeStorage(userId, sp); unlockUser(userId); @@ -2897,7 +2899,7 @@ public class LockSettingsService extends ILockSettings.Stub { mSpManager.clearSidForUser(userId); gateKeeperClearSecureUserId(userId); - unlockUserKey(userId, sp); + unlockCeStorage(userId, sp); unlockKeystore(userId, sp); setKeystorePassword(null, userId); removeBiometricsForUser(userId); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 7e88e13e1788853d24be2e6ac5792e3291363b0d..e5c19f575eba2f583d0779dfe9848023f306096e 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4905,9 +4905,9 @@ public class UserManagerService extends IUserManager.Stub { } } - t.traceBegin("createUserKey"); + t.traceBegin("createUserStorageKeys"); final StorageManager storage = mContext.getSystemService(StorageManager.class); - storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral()); + storage.createUserStorageKeys(userId, userInfo.serialNumber, userInfo.isEphemeral()); t.traceEnd(); // Only prepare DE storage here. CE storage will be prepared later, when the user is @@ -5731,17 +5731,18 @@ public class UserManagerService extends IUserManager.Stub { private void removeUserState(final @UserIdInt int userId) { Slog.i(LOG_TAG, "Removing user state of user " + userId); - // Cleanup lock settings. This must happen before destroyUserKey(), since the user's DE - // storage must still be accessible for the lock settings state to be properly cleaned up. + // Cleanup lock settings. This requires that the user's DE storage still be accessible, so + // this must happen before destroyUserStorageKeys(). mLockPatternUtils.removeUser(userId); // Evict and destroy the user's CE and DE encryption keys. At this point, the user's CE and // DE storage is made inaccessible, except to delete its contents. try { - mContext.getSystemService(StorageManager.class).destroyUserKey(userId); + mContext.getSystemService(StorageManager.class).destroyUserStorageKeys(userId); } catch (IllegalStateException e) { // This may be simply because the user was partially created. - Slog.i(LOG_TAG, "Destroying key for user " + userId + " failed, continuing anyway", e); + Slog.i(LOG_TAG, "Destroying storage keys for user " + userId + + " failed, continuing anyway", e); } // Cleanup package manager settings diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index dccacb4d301acbac6219d0c908184ddfcda2232f..a3403bb3ec3926817dda5bcc2ce2c527b8df6c26 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -345,7 +345,7 @@ public class UserControllerTest { assertWithMessage("should not have received intents") .that(getActions(mInjector.mSentIntents)).isEmpty(); // TODO(b/140868593): should have received a USER_UNLOCK_MSG message as well, but it doesn't - // because StorageManager.isUserKeyUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to + // because StorageManager.isCeStorageUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to // properly fix it, we'd need to move this class to FrameworksMockingServicesTests so we can // mock static methods (but moving this class would involve changing the presubmit tests, // and the cascade effect goes on...). In fact, a better approach would to not assert the @@ -648,7 +648,7 @@ public class UserControllerTest { // checking. waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(0)) - .lockUserKey(anyInt()); + .lockCeStorage(anyInt()); addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, numerOfUserSwitches, true); @@ -663,7 +663,7 @@ public class UserControllerTest { mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(1)) - .lockUserKey(TEST_USER_ID); + .lockCeStorage(TEST_USER_ID); } /** @@ -757,7 +757,7 @@ public class UserControllerTest { mUserController.startUser(TEST_USER_ID, USER_START_MODE_BACKGROUND); verify(mInjector.mStorageManagerMock, never()) - .unlockUserKey(eq(TEST_USER_ID), anyInt(), any()); + .unlockCeStorage(eq(TEST_USER_ID), anyInt(), any()); } @Test @@ -1035,7 +1035,7 @@ public class UserControllerTest { mUserController.finishUserStopped(ussUser, delayedLocking); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0)) - .lockUserKey(userId); + .lockCeStorage(userId); } private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index fe2ac176949d9d19a98d79c31362983664bf579c..f5d50d1734667e1eb00e0e5a4f1fba70c26b63be 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -304,17 +304,17 @@ public abstract class BaseLockSettingsServiceTests { doAnswer(invocation -> { Object[] args = invocation.getArguments(); - mStorageManager.unlockUserKey(/* userId= */ (int) args[0], + mStorageManager.unlockCeStorage(/* userId= */ (int) args[0], /* secret= */ (byte[]) args[2]); return null; - }).when(sm).unlockUserKey(anyInt(), anyInt(), any()); + }).when(sm).unlockCeStorage(anyInt(), anyInt(), any()); doAnswer(invocation -> { Object[] args = invocation.getArguments(); - mStorageManager.setUserKeyProtection(/* userId= */ (int) args[0], + mStorageManager.setCeStorageProtection(/* userId= */ (int) args[0], /* secret= */ (byte[]) args[1]); return null; - }).when(sm).setUserKeyProtection(anyInt(), any()); + }).when(sm).setCeStorageProtection(anyInt(), any()); return sm; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java index 91f3fed01267f192d6979a64c12ac9c14c8bfcd4..c08ad134d74a5aab573f19c0dc91dd1f1fd6a16e 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java @@ -24,7 +24,7 @@ public class FakeStorageManager { private final ArrayMap<Integer, byte[]> mUserSecrets = new ArrayMap<>(); - public void setUserKeyProtection(int userId, byte[] secret) { + public void setCeStorageProtection(int userId, byte[] secret) { assertThat(mUserSecrets).doesNotContainKey(userId); mUserSecrets.put(userId, secret); } @@ -35,7 +35,7 @@ public class FakeStorageManager { return secret; } - public void unlockUserKey(int userId, byte[] secret) { + public void unlockCeStorage(int userId, byte[] secret) { assertThat(mUserSecrets.get(userId)).isEqualTo(secret); } }