Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d5653e1 authored by Eric Biggers's avatar Eric Biggers
Browse files

Unlock user keys from LockSettingsService only

In preparation for making the CE key of each user always be protected by
the user's synthetic password even when the user has no LSKF, make
LockSettingsService the sole caller of IStorageManager.unlockUserKey().

For the opportunistic secret-less unlock by UserController at user start
time, call a new method LSS.unlockUserKeyIfUnsecured().  For now this
method calls IStorageManager.unlockUserKey() with a null secret.  Later
it will unwrap the user's synthetic password if needed.

For the unlock via credential verification that is triggered by LSS,
make LSS call IStorageManager.unlockUserKey() before calling
IActivityManager.unlockUser(), rather than passing the SP-derived secret
to IActivityManager.unlockUser() for it to do the unlockUserKey().

Since neither the secret nor the token arguments to
IActivityManager.unlockUser() are used anymore, add a new method
IActivityManager.unlockUser2() that lacks these arguments.  Note that
method name overloading cannot be used because AIDL doesn't support it.

Test: atest com.android.server.locksettings && \
      atest com.android.server.am.UserControllerTest \
            com.android.server.pm.UserManagerServiceTest \
            com.android.server.pm.UserManagerTest
Test: Boot and reboot Cuttlefish
Bug: 232452368
Change-Id: I8971b92bb5055fca8e19e0f9d14e8f0a7022b453
parent 883e1b9f
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -524,9 +524,30 @@ interface IActivityManager {

    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
    void suppressResizeConfigChanges(boolean suppress);

    /**
     * @deprecated Use {@link #unlockUser2(int, IProgressListener)} instead, since the token and
     * secret arguments no longer do anything.  This method still exists only because it is marked
     * with {@code @UnsupportedAppUsage}, so it might not be safe to remove it or change its
     * signature.
     */
    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
    boolean unlockUser(int userid, in byte[] token, in byte[] secret,
            in IProgressListener listener);

    /**
     * Tries to unlock the given user.
     * <p>
     * This will succeed only if the user's CE storage key is already unlocked or if the user
     * doesn't have a lockscreen credential set.
     *
     * @param userId The ID of the user to unlock.
     * @param listener An optional progress listener.
     *
     * @return true if the user was successfully unlocked, otherwise false.
     */
    boolean unlockUser2(int userId, in IProgressListener listener);

    void killPackageDependents(in String packageName, int userId);
    void makePackageIdle(String packageName, int userId);
    int getMemoryTrimLevel();
+1 −0
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ interface IStorageManager {
    void createUserKey(int userId, int serialNumber, boolean ephemeral) = 61;
    @EnforcePermission("STORAGE_INTERNAL")
    void destroyUserKey(int userId) = 62;
    @EnforcePermission("STORAGE_INTERNAL")
    void unlockUserKey(int userId, int serialNumber, in byte[] secret) = 63;
    @EnforcePermission("STORAGE_INTERNAL")
    void lockUserKey(int userId) = 64;
+0 −9
Original line number Diff line number Diff line
@@ -1605,15 +1605,6 @@ public class StorageManager {
        }
    }

    /** {@hide} */
    public void unlockUserKey(int userId, int serialNumber, byte[] secret) {
        try {
            mStorageManager.unlockUserKey(userId, serialNumber, secret);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** {@hide} */
    public void lockUserKey(int userId) {
        try {
+5 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
import android.app.admin.PasswordMetrics;
@@ -1784,4 +1785,8 @@ public class LockPatternUtils {
            re.rethrowFromSystemServer();
        }
    }

    public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
        getLockSettingsInternal().unlockUserKeyIfUnsecured(userId);
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.widget;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.admin.PasswordMetrics;

import java.lang.annotation.Retention;
@@ -52,6 +53,17 @@ public abstract class LockSettingsInternal {
    public static final int ARM_REBOOT_ERROR_STORE_ESCROW_KEY = 7;
    // TODO(b/183140900) split store escrow key errors into detailed ones.

    /**
     * Unlocks the credential-encrypted storage for the given user if the user is not secured, i.e.
     * doesn't have an LSKF.
     * <p>
     * This doesn't throw an exception on failure; whether the storage has been unlocked can be
     * determined by {@link StorageManager#isUserKeyUnlocked()}.
     *
     * @param userId the ID of the user whose storage to unlock
     */
    public abstract void unlockUserKeyIfUnsecured(@UserIdInt int userId);

    /**
     * Create an escrow token for the current user, which can later be used to unlock FBE
     * or change user password.
Loading