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

Commit 56a9395a authored by Paul Crowley's avatar Paul Crowley Committed by Android (Google) Code Review
Browse files

Merge "Two phases to set the password for disk encryption" into nyc-dev

parents d24ad869 cc70155f
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();
        }