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

Commit 85a0ffe9 authored by Rubin Xu's avatar Rubin Xu
Browse files

Fix work profile with unified challenge in HSUM

Manually set the SID for the auth-bound key that protects unified
challenge to the one of the parent user.

Bug: 248248444
Test: atest com.android.server.locksettings
      atest ManagedProfilePasswordTest
Change-Id: I8dc9f5c4aed3d2eaa0104e526d7cdaa7edf92770
parent 5c6c5829
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -420,7 +420,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
            setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                    /* isLockTiedToParent= */ true);
            tieProfileLockToParent(profileUserId, unifiedProfilePassword);
            tieProfileLockToParent(profileUserId, parentId, unifiedProfilePassword);
            mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword);
        }
    }
@@ -1887,34 +1887,43 @@ public class LockSettingsService extends ILockSettings.Stub {
    }

    @VisibleForTesting /** Note: this method is overridden in unit tests */
    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
    protected void tieProfileLockToParent(int profileUserId, int parentUserId,
            LockscreenCredential password) {
        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + profileUserId);
        final byte[] iv;
        final byte[] ciphertext;
        final long parentSid;
        try {
            parentSid = getGateKeeperService().getSecureUserId(parentUserId);
        } catch (RemoteException e) {
            throw new IllegalStateException("Failed to talk to GateKeeper service", e);
        }

        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
            keyGenerator.init(new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            try {
                mJavaKeyStore.setEntry(
                        PROFILE_KEY_NAME_ENCRYPT + userId,
                        PROFILE_KEY_NAME_ENCRYPT + profileUserId,
                        new java.security.KeyStore.SecretKeyEntry(secretKey),
                        new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                .build());
                mJavaKeyStore.setEntry(
                        PROFILE_KEY_NAME_DECRYPT + userId,
                        PROFILE_KEY_NAME_DECRYPT + profileUserId,
                        new java.security.KeyStore.SecretKeyEntry(secretKey),
                        new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                .setUserAuthenticationRequired(true)
                                .setBoundToSpecificSecureUserId(parentSid)
                                .setUserAuthenticationValidityDurationSeconds(30)
                                .build());
                // Key imported, obtain a reference to it.
                SecretKey keyStoreEncryptionKey = (SecretKey) mJavaKeyStore.getKey(
                        PROFILE_KEY_NAME_ENCRYPT + userId, null);
                        PROFILE_KEY_NAME_ENCRYPT + profileUserId, null);
                Cipher cipher = Cipher.getInstance(
                        KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
                                + KeyProperties.ENCRYPTION_PADDING_NONE);
@@ -1923,7 +1932,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                iv = cipher.getIV();
            } finally {
                // The original key can now be discarded.
                mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + userId);
                mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + profileUserId);
            }
        } catch (UnrecoverableKeyException
                | BadPaddingException | IllegalBlockSizeException | KeyStoreException
@@ -1933,7 +1942,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        if (iv.length != PROFILE_KEY_IV_SIZE) {
            throw new IllegalArgumentException("Invalid iv length: " + iv.length);
        }
        mStorage.writeChildProfileLock(userId, ArrayUtils.concat(iv, ciphertext));
        mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext));
    }

    private void setUserKeyProtection(@UserIdInt int userId, byte[] secret) {
@@ -2045,7 +2054,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i);
                if (piUserId != -1 && piUserDecryptedPassword != null) {
                    if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
                    tieProfileLockToParent(piUserId, piUserDecryptedPassword);
                    tieProfileLockToParent(piUserId, userId, piUserDecryptedPassword);
                }
                if (piUserDecryptedPassword != null) {
                    piUserDecryptedPassword.zeroize();
+3 −2
Original line number Diff line number Diff line
@@ -165,10 +165,11 @@ public class LockSettingsServiceTestable extends LockSettingsService {
    }

    @Override
    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
    protected void tieProfileLockToParent(int profileUserId, int parentUserId,
            LockscreenCredential password) {
        Parcel parcel = Parcel.obtain();
        parcel.writeParcelable(password, 0);
        mStorage.writeChildProfileLock(userId, parcel.marshall());
        mStorage.writeChildProfileLock(profileUserId, parcel.marshall());
        parcel.recycle();
    }