From 85a0ffe9767b415dab2dd33aa8ae5452a095cd68 Mon Sep 17 00:00:00 2001 From: Rubin Xu Date: Tue, 24 Jan 2023 16:16:47 +0000 Subject: [PATCH] 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 --- .../locksettings/LockSettingsService.java | 27 ++++++++++++------- .../LockSettingsServiceTestable.java | 5 ++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 4013468481aba..0c6985574693b 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -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(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 9686c385e91e4..1c33d0de45681 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -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(); }