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

Commit 8968ed9e authored by Dmitry Dementyev's avatar Dmitry Dementyev Committed by Android (Google) Code Review
Browse files

Merge "Remove platform key when user disables lock screen protection"

parents c4181a7c 6e16724f
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -1348,11 +1348,11 @@ public class LockSettingsService extends ILockSettings.Stub {
                    .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
                    .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
            setUserKeyProtection(userId, credential, convertResponse(gkResponse));
            setUserKeyProtection(userId, credential, convertResponse(gkResponse));
            fixateNewestUserKeyAuth(userId);
            fixateNewestUserKeyAuth(userId);
            mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
                userId);
            // Refresh the auth token
            // Refresh the auth token
            doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
            doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
            mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
                userId);
        } else {
        } else {
            throw new RemoteException("Failed to enroll " +
            throw new RemoteException("Failed to enroll " +
                    (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
                    (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
@@ -2494,6 +2494,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                    (response != null ? "rate limit exceeded" : "failed"));
                    (response != null ? "rate limit exceeded" : "failed"));
            return;
            return;
        }
        }
        mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
    }
    }


    @Override
    @Override
+8 −9
Original line number Original line Diff line number Diff line
@@ -72,7 +72,7 @@ public class KeySyncTask implements Runnable {
    private final int mCredentialType;
    private final int mCredentialType;
    private final String mCredential;
    private final String mCredential;
    private final boolean mCredentialUpdated;
    private final boolean mCredentialUpdated;
    private final PlatformKeyManager.Factory mPlatformKeyManagerFactory;
    private final PlatformKeyManager mPlatformKeyManager;
    private final RecoverySnapshotStorage mRecoverySnapshotStorage;
    private final RecoverySnapshotStorage mRecoverySnapshotStorage;
    private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;
    private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;


@@ -94,7 +94,7 @@ public class KeySyncTask implements Runnable {
                credentialType,
                credentialType,
                credential,
                credential,
                credentialUpdated,
                credentialUpdated,
                () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
                PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
    }
    }


    /**
    /**
@@ -105,9 +105,7 @@ public class KeySyncTask implements Runnable {
     * @param credentialType The type of credential as defined in {@code LockPatternUtils}
     * @param credentialType The type of credential as defined in {@code LockPatternUtils}
     * @param credential The credential, encoded as a {@link String}.
     * @param credential The credential, encoded as a {@link String}.
     * @param credentialUpdated signals weather credentials were updated.
     * @param credentialUpdated signals weather credentials were updated.
     * @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user.
     * @param platformKeyManager platform key manager
     *     This is a factory to enable unit testing, as otherwise it would be impossible to test
     *     without a screen unlock occurring!
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    KeySyncTask(
    KeySyncTask(
@@ -118,14 +116,14 @@ public class KeySyncTask implements Runnable {
            int credentialType,
            int credentialType,
            String credential,
            String credential,
            boolean credentialUpdated,
            boolean credentialUpdated,
            PlatformKeyManager.Factory platformKeyManagerFactory) {
            PlatformKeyManager platformKeyManager) {
        mSnapshotListenersStorage = recoverySnapshotListenersStorage;
        mSnapshotListenersStorage = recoverySnapshotListenersStorage;
        mRecoverableKeyStoreDb = recoverableKeyStoreDb;
        mRecoverableKeyStoreDb = recoverableKeyStoreDb;
        mUserId = userId;
        mUserId = userId;
        mCredentialType = credentialType;
        mCredentialType = credentialType;
        mCredential = credential;
        mCredential = credential;
        mCredentialUpdated = credentialUpdated;
        mCredentialUpdated = credentialUpdated;
        mPlatformKeyManagerFactory = platformKeyManagerFactory;
        mPlatformKeyManager = platformKeyManager;
        mRecoverySnapshotStorage = snapshotStorage;
        mRecoverySnapshotStorage = snapshotStorage;
    }
    }


@@ -145,6 +143,8 @@ public class KeySyncTask implements Runnable {
        if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
        if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
            // Application keys for the user will not be available for sync.
            // Application keys for the user will not be available for sync.
            Log.w(TAG, "Credentials are not set for user " + mUserId);
            Log.w(TAG, "Credentials are not set for user " + mUserId);
            int generation = mPlatformKeyManager.getGenerationId(mUserId);
            mPlatformKeyManager.invalidatePlatformKey(mUserId, generation);
            return;
            return;
        }
        }


@@ -304,8 +304,7 @@ public class KeySyncTask implements Runnable {
            throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
            throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException,
            NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException,
            InvalidKeyException, InvalidAlgorithmParameterException {
            InvalidKeyException, InvalidAlgorithmParameterException {
        PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance();
        PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);;
        PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);;
        Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
        Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
                mUserId, recoveryAgentUid, decryptKey.getGenerationId());
                mUserId, recoveryAgentUid, decryptKey.getGenerationId());
        return WrappedKey.unwrapKeys(decryptKey, wrappedKeys);
        return WrappedKey.unwrapKeys(decryptKey, wrappedKeys);
+31 −14
Original line number Original line Diff line number Diff line
@@ -128,6 +128,26 @@ public class PlatformKeyManager {
        return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId);
        return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId);
    }
    }


    /**
     * Removes the platform key from Android KeyStore.
     * It is triggered when user disables lock screen.
     *
     * @param userId The ID of the user to whose lock screen the platform key must be bound.
     * @param generationId Generation id.
     *
     * @hide
     */
    public void invalidatePlatformKey(int userId, int generationId) {
        if (generationId != -1) {
            try {
                mKeyStore.deleteEntry(getEncryptAlias(userId, generationId));
                mKeyStore.deleteEntry(getDecryptAlias(userId, generationId));
            } catch (KeyStoreException e) {
                // Ignore failed attempt to delete key.
            }
        }
    }

    /**
    /**
     * Generates a new key and increments the generation ID. Should be invoked if the platform key
     * Generates a new key and increments the generation ID. Should be invoked if the platform key
     * is corrupted and needs to be rotated.
     * is corrupted and needs to be rotated.
@@ -152,6 +172,7 @@ public class PlatformKeyManager {
        if (generationId == -1) {
        if (generationId == -1) {
            nextId = 1;
            nextId = 1;
        } else {
        } else {
            invalidatePlatformKey(userId, generationId);
            nextId = generationId + 1;
            nextId = generationId + 1;
        }
        }
        generateAndLoadKey(userId, nextId);
        generateAndLoadKey(userId, nextId);
@@ -197,8 +218,12 @@ public class PlatformKeyManager {
    private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException,
    private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException,
           UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
           UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
        int generationId = getGenerationId(userId);
        int generationId = getGenerationId(userId);
        String alias = getEncryptAlias(userId, generationId);
        if (!mKeyStore.containsAlias(alias)) {
            throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
        }
        AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
        AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
                getEncryptAlias(userId, generationId), /*password=*/ null);
                alias, /*password=*/ null);
        return new PlatformEncryptionKey(generationId, key);
        return new PlatformEncryptionKey(generationId, key);
    }
    }


@@ -242,8 +267,12 @@ public class PlatformKeyManager {
    private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException,
    private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException,
           UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
           UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
        int generationId = getGenerationId(userId);
        int generationId = getGenerationId(userId);
        String alias = getDecryptAlias(userId, generationId);
        if (!mKeyStore.containsAlias(alias)) {
            throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
        }
        AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
        AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
                getDecryptAlias(userId, generationId), /*password=*/ null);
                alias, /*password=*/ null);
        return new PlatformDecryptionKey(generationId, key);
        return new PlatformDecryptionKey(generationId, key);
    }
    }


@@ -405,16 +434,4 @@ public class PlatformKeyManager {
        return keyStore;
        return keyStore;
    }
    }


    /**
     * @hide
     */
    public interface Factory {
        /**
         * New PlatformKeyManager instance.
         *
         * @hide
         */
        PlatformKeyManager newInstance()
                throws NoSuchAlgorithmException, InsecureUserException, KeyStoreException;
    }
}
}
+2 −1
Original line number Original line Diff line number Diff line
@@ -579,6 +579,7 @@ public class RecoverableKeyStoreManager {


    /**
    /**
     * This function can only be used inside LockSettingsService.
     * This function can only be used inside LockSettingsService.
     *
     * @param storedHashType from {@code CredentialHash}
     * @param storedHashType from {@code CredentialHash}
     * @param credential - unencrypted String
     * @param credential - unencrypted String
     * @param userId for the user whose lock screen credentials were changed.
     * @param userId for the user whose lock screen credentials were changed.
@@ -604,7 +605,7 @@ public class RecoverableKeyStoreManager {
        } catch (KeyStoreException e) {
        } catch (KeyStoreException e) {
            Log.e(TAG, "Key store error encountered during recoverable key sync", e);
            Log.e(TAG, "Key store error encountered during recoverable key sync", e);
        } catch (InsecureUserException e) {
        } catch (InsecureUserException e) {
            Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e);
            Log.e(TAG, "InsecureUserException during lock screen secret update", e);
        }
        }
    }
    }


+4 −4
Original line number Original line Diff line number Diff line
@@ -121,7 +121,7 @@ public class KeySyncTaskTest {
                TEST_CREDENTIAL_TYPE,
                TEST_CREDENTIAL_TYPE,
                TEST_CREDENTIAL,
                TEST_CREDENTIAL,
                /*credentialUpdated=*/ false,
                /*credentialUpdated=*/ false,
                () -> mPlatformKeyManager);
                mPlatformKeyManager);


        mWrappingKey = generateAndroidKeyStoreKey();
        mWrappingKey = generateAndroidKeyStoreKey();
        mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
        mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
@@ -352,7 +352,7 @@ public class KeySyncTaskTest {
                CREDENTIAL_TYPE_PASSWORD,
                CREDENTIAL_TYPE_PASSWORD,
                "password",
                "password",
                /*credentialUpdated=*/ false,
                /*credentialUpdated=*/ false,
                () -> mPlatformKeyManager);
                mPlatformKeyManager);


        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -378,7 +378,7 @@ public class KeySyncTaskTest {
                CREDENTIAL_TYPE_PASSWORD,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ "1234",
                /*credential=*/ "1234",
                /*credentialUpdated=*/ false,
                /*credentialUpdated=*/ false,
                () -> mPlatformKeyManager);
                mPlatformKeyManager);


        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -405,7 +405,7 @@ public class KeySyncTaskTest {
                CREDENTIAL_TYPE_PATTERN,
                CREDENTIAL_TYPE_PATTERN,
                "12345",
                "12345",
                /*credentialUpdated=*/ false,
                /*credentialUpdated=*/ false,
                () -> mPlatformKeyManager);
                mPlatformKeyManager);


        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
Loading