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

Commit add57fcc authored by Barani Muthukumaran's avatar Barani Muthukumaran Committed by Paul Crowley
Browse files

Provide secret to vold to remove credential

vold requires the secret to retrieve the CE key
to re-wrap without auth when the user removes
the credential.

Test: Set credential, remove credential, swipe to none
and vice-versa.
Unit tests under locksettings

Bug: 26948053
Merged-In: I14503404ddd330cced2f2ff0e8f500cbe3f96e28
Change-Id: I14503404ddd330cced2f2ff0e8f500cbe3f96e28
parent 0b93d2b1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -193,4 +193,5 @@ interface IStorageManager {
    void startCheckpoint(int numTries) = 85;
    boolean needsCheckpoint() = 86;
    void abortChanges(in String message, boolean retry) = 87;
    void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88;
}
+18 −0
Original line number Diff line number Diff line
@@ -2787,6 +2787,24 @@ class StorageManagerService extends IStorageManager.Stub
        }
    }

    /*
     * Clear disk encryption key bound to the associated token / secret pair. Removing the user
     * binding of the Disk encryption key is done in two phases: first, this call will retrieve
     * the disk encryption key using the provided token / secret pair and store it by
     * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
     * is called to delete all other bindings of the disk encryption key.
     */
    @Override
    public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);

        try {
            mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
        } catch (Exception e) {
            Slog.wtf(TAG, e);
        }
    }

    /*
     * Delete all disk encryption token/secret pairs except the most recently added one
     */
+13 −5
Original line number Diff line number Diff line
@@ -1510,7 +1510,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            if (credential != null) {
                Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
            }
            clearUserKeyProtection(userId);
            clearUserKeyProtection(userId, null);
            getGateKeeperService().clearSecureUserId(userId);
            mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
            setKeystorePassword(null, userId);
@@ -1687,9 +1687,17 @@ public class LockSettingsService extends ILockSettings.Stub {
        addUserKeyAuth(userId, token, secretFromCredential(credential));
    }

    private void clearUserKeyProtection(int userId) throws RemoteException {
    private void clearUserKeyProtection(int userId, byte[] secret) {
        if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
        addUserKeyAuth(userId, null, null);
        final UserInfo userInfo = mUserManager.getUserInfo(userId);
        final long callingId = Binder.clearCallingIdentity();
        try {
            mStorageManager.clearUserKeyAuth(userId, userInfo.serialNumber, null, secret);
        } catch (RemoteException e) {
            throw new IllegalStateException("clearUserKeyAuth failed user=" + userId);
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }

    private static byte[] secretFromCredential(byte[] credential) throws RemoteException {
@@ -2511,7 +2519,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
            setKeystorePassword(auth.deriveKeyStorePassword(), userId);
        } else {
            clearUserKeyProtection(userId);
            clearUserKeyProtection(userId, null);
            setKeystorePassword(null, userId);
            getGateKeeperService().clearSecureUserId(userId);
        }
@@ -2686,7 +2694,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            // during boot. Vold storage needs to be unlocked before manipulation of the keys can
            // succeed.
            unlockUserKey(userId, null, auth.deriveDiskEncryptionKey());
            clearUserKeyProtection(userId);
            clearUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
            fixateNewestUserKeyAuth(userId);
            unlockKeystore(auth.deriveKeyStorePassword(), userId);
            setKeystorePassword(null, userId);
+12 −0
Original line number Diff line number Diff line
@@ -215,6 +215,18 @@ public abstract class BaseLockSettingsServiceTests {
            }
        }).when(sm).addUserKeyAuth(anyInt(), anyInt(), any(), any());

        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                mStorageManager.clearUserKeyAuth((int) args[0] /* userId */,
                        (int) args[1] /* serialNumber */,
                        (byte[]) args[2] /* token */,
                        (byte[]) args[3] /* secret */);
                return null;
            }
        }).when(sm).clearUserKeyAuth(anyInt(), anyInt(), any(), any());

        doAnswer(
                new Answer<Void>() {
            @Override
+9 −0
Original line number Diff line number Diff line
@@ -36,6 +36,15 @@ public class FakeStorageManager {
        getUserAuth(userId).add(new Pair<>(token, secret));
    }

    public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
        if (token == null && secret == null) {
            return;
        }
        auths.remove(new Pair<>(token, secret));
        auths.add(new Pair<>(null, null));
    }

    public void fixateNewestUserKeyAuth(int userId) {
        ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId);
        Pair<byte[], byte[]> latest = auths.get(auths.size() - 1);