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

Commit 47eb5a7d authored by Paul Crowley's avatar Paul Crowley Committed by android-build-merger
Browse files

Merge "Two phases to set the password for disk encryption" into nyc-dev am: 56a9395a

am: 3ddb6d5f

* commit '3ddb6d5f':
  Two phases to set the password for disk encryption

Change-Id: Icc4ede9459833b3c8879514b15fd3b5aba9be812
parents 643a9a79 3ddb6d5f
Loading
Loading
Loading
Loading
+35 −12
Original line number Diff line number Diff line
@@ -1233,8 +1233,8 @@ public interface IMountService extends IInterface {
            }

            @Override
            public void changeUserKey(int userId, int serialNumber,
                    byte[] token, byte[] oldSecret, byte[] newSecret) throws RemoteException {
            public void addUserKeyAuth(int userId, int serialNumber,
                    byte[] token, byte[] secret) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                try {
@@ -1242,9 +1242,23 @@ public interface IMountService extends IInterface {
                    _data.writeInt(userId);
                    _data.writeInt(serialNumber);
                    _data.writeByteArray(token);
                    _data.writeByteArray(oldSecret);
                    _data.writeByteArray(newSecret);
                    mRemote.transact(Stub.TRANSACTION_changeUserKey, _data, _reply, 0);
                    _data.writeByteArray(secret);
                    mRemote.transact(Stub.TRANSACTION_addUserKeyAuth, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void fixateNewestUserKeyAuth(int userId) throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(userId);
                    mRemote.transact(Stub.TRANSACTION_fixateNewestUserKeyAuth, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
@@ -1489,7 +1503,9 @@ public interface IMountService extends IInterface {

        static final int TRANSACTION_mountAppFuse = IBinder.FIRST_CALL_TRANSACTION + 69;

        static final int TRANSACTION_changeUserKey = IBinder.FIRST_CALL_TRANSACTION + 70;
        static final int TRANSACTION_addUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 70;

        static final int TRANSACTION_fixateNewestUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 71;

        /**
         * Cast an IBinder object into an IMountService interface, generating a
@@ -2069,14 +2085,20 @@ public interface IMountService extends IInterface {
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_changeUserKey: {
                case TRANSACTION_addUserKeyAuth: {
                    data.enforceInterface(DESCRIPTOR);
                    int userId = data.readInt();
                    int serialNumber = data.readInt();
                    byte[] token = data.createByteArray();
                    byte[] oldSecret = data.createByteArray();
                    byte[] newSecret = data.createByteArray();
                    changeUserKey(userId, serialNumber, token, oldSecret, newSecret);
                    byte[] secret = data.createByteArray();
                    addUserKeyAuth(userId, serialNumber, token, secret);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_fixateNewestUserKeyAuth: {
                    data.enforceInterface(DESCRIPTOR);
                    int userId = data.readInt();
                    fixateNewestUserKeyAuth(userId);
                    reply.writeNoException();
                    return true;
                }
@@ -2452,8 +2474,9 @@ public interface IMountService extends IInterface {
    public void createUserKey(int userId, int serialNumber, boolean ephemeral)
            throws RemoteException;
    public void destroyUserKey(int userId) throws RemoteException;
    public void changeUserKey(int userId, int serialNumber,
            byte[] token, byte[] oldSecret, byte[] newSecret) throws RemoteException;
    public void addUserKeyAuth(int userId, int serialNumber,
            byte[] token, byte[] secret) throws RemoteException;
    public void fixateNewestUserKeyAuth(int userId) throws RemoteException;

    public void unlockUserKey(int userId, int serialNumber,
            byte[] token, byte[] secret) throws RemoteException;
+35 −10
Original line number Diff line number Diff line
@@ -790,10 +790,11 @@ public class LockSettingsService extends ILockSettings.Stub {
                if (isSecure) {
                    tieManagedProfileLockIfNecessary(managedUserId, null);
                } else {
                    clearUserKeyProtection(managedUserId);
                    getGateKeeperService().clearSecureUserId(managedUserId);
                    mStorage.writePatternHash(null, managedUserId);
                    setKeystorePassword(null, managedUserId);
                    clearUserKeyProtection(managedUserId);
                    fixateNewestUserKeyAuth(managedUserId);
                    mStorage.removeChildProfileLock(managedUserId);
                    removeKeystoreProfileKey(managedUserId);
                }
@@ -828,10 +829,11 @@ public class LockSettingsService extends ILockSettings.Stub {
        byte[] currentHandle = getCurrentHandle(userId);

        if (pattern == null) {
            clearUserKeyProtection(userId);
            getGateKeeperService().clearSecureUserId(userId);
            mStorage.writePatternHash(null, userId);
            setKeystorePassword(null, userId);
            clearUserKeyProtection(userId);
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
            return;
        }
@@ -861,8 +863,12 @@ public class LockSettingsService extends ILockSettings.Stub {

        byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
        if (enrolledHandle != null) {
            CredentialHash willStore
                = new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
            setUserKeyProtection(userId, pattern,
                doVerifyPattern(pattern, willStore, true, 0, userId));
            mStorage.writePatternHash(enrolledHandle, userId);
            setUserKeyProtection(userId, pattern, verifyPattern(pattern, 0, userId));
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
        } else {
            throw new RemoteException("Failed to enroll pattern");
@@ -885,10 +891,11 @@ public class LockSettingsService extends ILockSettings.Stub {
            throws RemoteException {
        byte[] currentHandle = getCurrentHandle(userId);
        if (password == null) {
            clearUserKeyProtection(userId);
            getGateKeeperService().clearSecureUserId(userId);
            mStorage.writePasswordHash(null, userId);
            setKeystorePassword(null, userId);
            clearUserKeyProtection(userId);
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
            return;
        }
@@ -916,8 +923,12 @@ public class LockSettingsService extends ILockSettings.Stub {

        byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
        if (enrolledHandle != null) {
            CredentialHash willStore
                = new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
            setUserKeyProtection(userId, password,
                doVerifyPassword(password, willStore, true, 0, userId));
            mStorage.writePasswordHash(enrolledHandle, userId);
            setUserKeyProtection(userId, password, verifyPassword(password, 0, userId));
            fixateNewestUserKeyAuth(userId);
            onUserLockChanged(userId);
        } else {
            throw new RemoteException("Failed to enroll password");
@@ -1022,11 +1033,11 @@ public class LockSettingsService extends ILockSettings.Stub {
        if (token == null) {
            throw new RemoteException("Empty payload verifying a credential we just set");
        }
        changeUserKey(userId, token, secretFromCredential(credential));
        addUserKeyAuth(userId, token, secretFromCredential(credential));
    }

    private void clearUserKeyProtection(int userId) throws RemoteException {
        changeUserKey(userId, null, null);
        addUserKeyAuth(userId, null, null);
    }

    private static byte[] secretFromCredential(String credential) throws RemoteException {
@@ -1045,18 +1056,23 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    }

    private void changeUserKey(int userId, byte[] token, byte[] secret)
    private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
            throws RemoteException {
        final UserInfo userInfo = UserManager.get(mContext).getUserInfo(userId);
        final IMountService mountService = getMountService();
        final long callingId = Binder.clearCallingIdentity();
        try {
            mountService.changeUserKey(userId, userInfo.serialNumber, token, null, secret);
            mountService.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }

    private void fixateNewestUserKeyAuth(int userId)
            throws RemoteException {
        getMountService().fixateNewestUserKeyAuth(userId);
    }

    @Override
    public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
        return doVerifyPattern(pattern, false, 0, userId);
@@ -1072,6 +1088,11 @@ public class LockSettingsService extends ILockSettings.Stub {
            long challenge, int userId) throws RemoteException {
       checkPasswordReadPermission(userId);
       CredentialHash storedHash = mStorage.readPatternHash(userId);
       return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId);
    }

    private VerifyCredentialResponse doVerifyPattern(String pattern, CredentialHash storedHash,
            boolean hasChallenge, long challenge, int userId) throws RemoteException {
       boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;

       String patternToVerify;
@@ -1109,7 +1130,6 @@ public class LockSettingsService extends ILockSettings.Stub {
       }

       return response;

    }

    @Override
@@ -1159,6 +1179,11 @@ public class LockSettingsService extends ILockSettings.Stub {
            long challenge, int userId) throws RemoteException {
       checkPasswordReadPermission(userId);
       CredentialHash storedHash = mStorage.readPasswordHash(userId);
       return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId);
    }

    private VerifyCredentialResponse doVerifyPassword(String password, CredentialHash storedHash,
            boolean hasChallenge, long challenge, int userId) throws RemoteException {
       return verifyCredential(userId, storedHash, password, hasChallenge, challenge,
               new CredentialUtil() {
                   @Override
+1 −1
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ class LockSettingsStorage {

    private SparseArray<Integer> mStoredCredentialType;

    class CredentialHash {
    static class CredentialHash {
        static final int TYPE_NONE = -1;
        static final int TYPE_PATTERN = 1;
        static final int TYPE_PASSWORD = 2;
+25 −4
Original line number Diff line number Diff line
@@ -2816,15 +2816,36 @@ class MountService extends IMountService.Stub
        }
    }

    /*
     * Add this token/secret pair to the set of ways we can recover a disk encryption key.
     * Changing the token/secret for a disk encryption key is done in two phases: first, adding
     * a new token/secret pair with this call, then delting all other pairs with
     * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
     * Gatekeeper, to be updated between the two calls.
     */
    @Override
    public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
        waitForReady();

        try {
            mCryptConnector.execute("cryptfs", "add_user_key_auth", userId, serialNumber,
                encodeBytes(token), encodeBytes(secret));
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }
    }

    /*
     * Delete all disk encryption token/secret pairs except the most recently added one
     */
    @Override
    public void changeUserKey(int userId, int serialNumber,
            byte[] token, byte[] oldSecret, byte[] newSecret) {
    public void fixateNewestUserKeyAuth(int userId) {
        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
        waitForReady();

        try {
            mCryptConnector.execute("cryptfs", "change_user_key", userId, serialNumber,
                encodeBytes(token), encodeBytes(oldSecret), encodeBytes(newSecret));
            mCryptConnector.execute("cryptfs", "fixate_newest_user_key_auth", userId);
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }