Merge "LockSettingsService: migrate to its own keystore namespace" am: b8e5426266 am: fc7a26cd21
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1675900 Change-Id: I987c4a882529bf55ba9697889347b6a50b583942
This commit is contained in:
@@ -29,6 +29,8 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
|
||||
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
|
||||
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
|
||||
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
|
||||
import static com.android.internal.widget.LockPatternUtils.PROFILE_KEY_NAME_DECRYPT;
|
||||
import static com.android.internal.widget.LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT;
|
||||
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
|
||||
@@ -99,6 +101,7 @@ import android.security.keystore.recovery.KeyChainProtectionParams;
|
||||
import android.security.keystore.recovery.KeyChainSnapshot;
|
||||
import android.security.keystore.recovery.RecoveryCertPath;
|
||||
import android.security.keystore.recovery.WrappedApplicationKey;
|
||||
import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
|
||||
import android.security.keystore2.AndroidKeyStoreProvider;
|
||||
import android.service.gatekeeper.GateKeeperResponse;
|
||||
import android.service.gatekeeper.IGateKeeperService;
|
||||
@@ -153,6 +156,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
@@ -225,6 +229,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private final SyntheticPasswordManager mSpManager;
|
||||
|
||||
private final KeyStore mKeyStore;
|
||||
private final java.security.KeyStore mJavaKeyStore;
|
||||
private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
|
||||
private ManagedProfilePasswordCache mManagedProfilePasswordCache;
|
||||
|
||||
@@ -543,16 +548,22 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
return Settings.Secure.getIntForUser(contentResolver, keyName, defaultValue, userId);
|
||||
}
|
||||
|
||||
public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache() {
|
||||
public java.security.KeyStore getJavaKeyStore() {
|
||||
try {
|
||||
java.security.KeyStore ks = java.security.KeyStore.getInstance(
|
||||
SyntheticPasswordCrypto.androidKeystoreProviderName());
|
||||
ks.load(null);
|
||||
return new ManagedProfilePasswordCache(ks, getUserManager());
|
||||
ks.load(new AndroidKeyStoreLoadStoreParameter(
|
||||
SyntheticPasswordCrypto.keyNamespace()));
|
||||
return ks;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot load keystore", e);
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache(
|
||||
java.security.KeyStore ks) {
|
||||
return new ManagedProfilePasswordCache(ks, getUserManager());
|
||||
}
|
||||
}
|
||||
|
||||
public LockSettingsService(Context context) {
|
||||
@@ -564,6 +575,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
mInjector = injector;
|
||||
mContext = injector.getContext();
|
||||
mKeyStore = injector.getKeyStore();
|
||||
mJavaKeyStore = injector.getJavaKeyStore();
|
||||
mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager();
|
||||
mHandler = injector.getHandler(injector.getServiceThread());
|
||||
mStrongAuth = injector.getStrongAuth();
|
||||
@@ -586,7 +598,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
mStrongAuthTracker.register(mStrongAuth);
|
||||
|
||||
mSpManager = injector.getSyntheticPasswordManager(mStorage);
|
||||
mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache();
|
||||
mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache(mJavaKeyStore);
|
||||
|
||||
mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(),
|
||||
mStorage);
|
||||
@@ -959,6 +971,21 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
setString("migrated_wear_lockscreen_disabled", "true", 0);
|
||||
Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
|
||||
}
|
||||
|
||||
if (getString("migrated_keystore_namespace", null, 0) == null) {
|
||||
boolean success = true;
|
||||
synchronized (mSpManager) {
|
||||
success &= mSpManager.migrateKeyNamespace();
|
||||
}
|
||||
success &= migrateProfileLockKeys();
|
||||
if (success) {
|
||||
setString("migrated_keystore_namespace", "true", 0);
|
||||
Slog.i(TAG, "Migrated keys to LSS namespace");
|
||||
} else {
|
||||
Slog.w(TAG, "Failed to migrate keys to LSS namespace");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void migrateOldDataAfterSystemReady() {
|
||||
@@ -999,6 +1026,22 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean migrateProfileLockKeys() {
|
||||
boolean success = true;
|
||||
final List<UserInfo> users = mUserManager.getUsers();
|
||||
final int userCount = users.size();
|
||||
for (int i = 0; i < userCount; i++) {
|
||||
UserInfo user = users.get(i);
|
||||
if (user.isManagedProfile() && !getSeparateProfileChallengeEnabledInternal(user.id)) {
|
||||
success &= SyntheticPasswordCrypto.migrateLockSettingsKey(
|
||||
PROFILE_KEY_NAME_ENCRYPT + user.id);
|
||||
success &= SyntheticPasswordCrypto.migrateLockSettingsKey(
|
||||
PROFILE_KEY_NAME_DECRYPT + user.id);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowest password quality that still presents the same UI for entering it.
|
||||
*
|
||||
@@ -1284,11 +1327,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
|
||||
storedData.length);
|
||||
byte[] decryptionResult;
|
||||
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
|
||||
SyntheticPasswordCrypto.androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
SecretKey decryptionKey = (SecretKey) keyStore.getKey(
|
||||
LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
|
||||
SecretKey decryptionKey = (SecretKey) mJavaKeyStore.getKey(
|
||||
PROFILE_KEY_NAME_DECRYPT + userId, null);
|
||||
|
||||
Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
|
||||
+ KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
|
||||
@@ -1744,30 +1784,26 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
|
||||
keyGenerator.init(new SecureRandom());
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
|
||||
SyntheticPasswordCrypto.androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
try {
|
||||
keyStore.setEntry(
|
||||
LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
|
||||
mJavaKeyStore.setEntry(
|
||||
PROFILE_KEY_NAME_ENCRYPT + userId,
|
||||
new java.security.KeyStore.SecretKeyEntry(secretKey),
|
||||
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.build());
|
||||
keyStore.setEntry(
|
||||
LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
|
||||
mJavaKeyStore.setEntry(
|
||||
PROFILE_KEY_NAME_DECRYPT + userId,
|
||||
new java.security.KeyStore.SecretKeyEntry(secretKey),
|
||||
new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.setUserAuthenticationRequired(true)
|
||||
.setUserAuthenticationValidityDurationSeconds(30)
|
||||
.setCriticalToDeviceEncryption(true)
|
||||
.build());
|
||||
// Key imported, obtain a reference to it.
|
||||
SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
|
||||
LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
|
||||
SecretKey keyStoreEncryptionKey = (SecretKey) mJavaKeyStore.getKey(
|
||||
PROFILE_KEY_NAME_ENCRYPT + userId, null);
|
||||
Cipher cipher = Cipher.getInstance(
|
||||
KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
|
||||
+ KeyProperties.ENCRYPTION_PADDING_NONE);
|
||||
@@ -1776,10 +1812,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
iv = cipher.getIV();
|
||||
} finally {
|
||||
// The original key can now be discarded.
|
||||
keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
|
||||
mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + userId);
|
||||
}
|
||||
} catch (CertificateException | UnrecoverableKeyException
|
||||
| IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
|
||||
} catch (UnrecoverableKeyException
|
||||
| BadPaddingException | IllegalBlockSizeException | KeyStoreException
|
||||
| NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
throw new IllegalStateException("Failed to encrypt key", e);
|
||||
}
|
||||
@@ -2300,13 +2336,9 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private void removeKeystoreProfileKey(int targetUserId) {
|
||||
Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId);
|
||||
try {
|
||||
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(
|
||||
SyntheticPasswordCrypto.androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
|
||||
keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
|
||||
| IOException e) {
|
||||
mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
|
||||
mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
|
||||
} catch (KeyStoreException e) {
|
||||
// We have tried our best to remove all keys
|
||||
Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
|
||||
}
|
||||
@@ -3257,6 +3289,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
pw.println();
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println("Keys in namespace:");
|
||||
pw.increaseIndent();
|
||||
dumpKeystoreKeys(pw);
|
||||
pw.println();
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println("Storage:");
|
||||
pw.increaseIndent();
|
||||
mStorage.dump(pw);
|
||||
@@ -3276,6 +3314,18 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
private void dumpKeystoreKeys(IndentingPrintWriter pw) {
|
||||
try {
|
||||
final Enumeration<String> aliases = mJavaKeyStore.aliases();
|
||||
while (aliases.hasMoreElements()) {
|
||||
pw.println(aliases.nextElement());
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
pw.println("Unable to get keys: " + e.toString());
|
||||
Slog.d(TAG, "Dump error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cryptographically disable escrow token support for the current user, if the user is not
|
||||
* managed (either user has a profile owner, or if device is managed). Do not disable
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.os.UserManager;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.security.keystore.UserNotAuthenticatedException;
|
||||
import android.security.keystore2.AndroidKeyStoreSpi;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
|
||||
@@ -95,11 +94,12 @@ public class ManagedProfilePasswordCache {
|
||||
SecretKey key;
|
||||
try {
|
||||
generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,
|
||||
AndroidKeyStoreSpi.NAME);
|
||||
mKeyStore.getProvider());
|
||||
generator.init(new KeyGenParameterSpec.Builder(
|
||||
keyName, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
|
||||
.setKeySize(KEY_LENGTH)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setNamespace(SyntheticPasswordCrypto.keyNamespace())
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
// Generate auth-bound key to user 0 (since we the caller is user 0)
|
||||
.setUserAuthenticationRequired(true)
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package com.android.server.locksettings;
|
||||
|
||||
import android.security.AndroidKeyStoreMaintenance;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.security.keystore.KeyProtection;
|
||||
import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
|
||||
import android.system.keystore2.Domain;
|
||||
import android.system.keystore2.KeyDescriptor;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -125,9 +129,7 @@ public class SyntheticPasswordCrypto {
|
||||
|
||||
public static byte[] decryptBlobV1(String keyAlias, byte[] blob, byte[] applicationId) {
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
|
||||
KeyStore keyStore = getKeyStore();
|
||||
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
|
||||
if (decryptionKey == null) {
|
||||
throw new IllegalStateException("SP key is missing: " + keyAlias);
|
||||
@@ -144,10 +146,20 @@ public class SyntheticPasswordCrypto {
|
||||
return "AndroidKeyStore";
|
||||
}
|
||||
|
||||
static int keyNamespace() {
|
||||
return KeyProperties.NAMESPACE_LOCKSETTINGS;
|
||||
}
|
||||
|
||||
private static KeyStore getKeyStore()
|
||||
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
|
||||
KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
|
||||
keyStore.load(new AndroidKeyStoreLoadStoreParameter(keyNamespace()));
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
final KeyStore keyStore = getKeyStore();
|
||||
|
||||
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
|
||||
if (decryptionKey == null) {
|
||||
@@ -170,8 +182,7 @@ public class SyntheticPasswordCrypto {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
|
||||
keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom());
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
KeyStore keyStore = KeyStore.getInstance(androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
final KeyStore keyStore = getKeyStore();
|
||||
KeyProtection.Builder builder = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
@@ -200,8 +211,7 @@ public class SyntheticPasswordCrypto {
|
||||
public static void destroyBlobKey(String keyAlias) {
|
||||
KeyStore keyStore;
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(androidKeystoreProviderName());
|
||||
keyStore.load(null);
|
||||
keyStore = getKeyStore();
|
||||
keyStore.deleteEntry(keyAlias);
|
||||
Slog.i(TAG, "SP key deleted: " + keyAlias);
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
|
||||
@@ -229,4 +239,32 @@ public class SyntheticPasswordCrypto {
|
||||
throw new IllegalStateException("NoSuchAlgorithmException for SHA-512", e);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean migrateLockSettingsKey(String alias) {
|
||||
final KeyDescriptor legacyKey = new KeyDescriptor();
|
||||
legacyKey.domain = Domain.APP;
|
||||
legacyKey.nspace = KeyProperties.NAMESPACE_APPLICATION;
|
||||
legacyKey.alias = alias;
|
||||
|
||||
final KeyDescriptor newKey = new KeyDescriptor();
|
||||
newKey.domain = Domain.SELINUX;
|
||||
newKey.nspace = SyntheticPasswordCrypto.keyNamespace();
|
||||
newKey.alias = alias;
|
||||
Slog.i(TAG, "Migrating key " + alias);
|
||||
int err = AndroidKeyStoreMaintenance.migrateKeyNamespace(legacyKey, newKey);
|
||||
if (err == 0) {
|
||||
return true;
|
||||
} else if (err == AndroidKeyStoreMaintenance.KEY_NOT_FOUND) {
|
||||
Slog.i(TAG, "Key does not exist");
|
||||
// Treat this as a success so we don't migrate again.
|
||||
return true;
|
||||
} else if (err == AndroidKeyStoreMaintenance.INVALID_ARGUMENT) {
|
||||
Slog.i(TAG, "Key already exists");
|
||||
// Treat this as a success so we don't migrate again.
|
||||
return true;
|
||||
} else {
|
||||
Slog.e(TAG, String.format("Failed to migrate key: %d", err));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ public class SyntheticPasswordManager {
|
||||
public void removeUser(int userId) {
|
||||
for (long handle : mStorage.listSyntheticPasswordHandlesForUser(SP_BLOB_NAME, userId)) {
|
||||
destroyWeaverSlot(handle, userId);
|
||||
destroySPBlobKey(getHandleName(handle));
|
||||
destroySPBlobKey(getKeyName(handle));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,7 +956,7 @@ public class SyntheticPasswordManager {
|
||||
} else {
|
||||
secret = authToken.getSyntheticPassword();
|
||||
}
|
||||
byte[] content = createSPBlob(getHandleName(handle), secret, applicationId, sid);
|
||||
byte[] content = createSPBlob(getKeyName(handle), secret, applicationId, sid);
|
||||
byte[] blob = new byte[content.length + 1 + 1];
|
||||
/*
|
||||
* We can upgrade from v1 to v2 because that's just a change in the way that
|
||||
@@ -1138,10 +1138,10 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
final byte[] secret;
|
||||
if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
|
||||
secret = SyntheticPasswordCrypto.decryptBlobV1(getHandleName(handle),
|
||||
secret = SyntheticPasswordCrypto.decryptBlobV1(getKeyName(handle),
|
||||
Arrays.copyOfRange(blob, 2, blob.length), applicationId);
|
||||
} else {
|
||||
secret = decryptSPBlob(getHandleName(handle),
|
||||
secret = decryptSPBlob(getKeyName(handle),
|
||||
Arrays.copyOfRange(blob, 2, blob.length), applicationId);
|
||||
}
|
||||
if (secret == null) {
|
||||
@@ -1236,7 +1236,7 @@ public class SyntheticPasswordManager {
|
||||
|
||||
private void destroySyntheticPassword(long handle, int userId) {
|
||||
destroyState(SP_BLOB_NAME, handle, userId);
|
||||
destroySPBlobKey(getHandleName(handle));
|
||||
destroySPBlobKey(getKeyName(handle));
|
||||
if (hasState(WEAVER_SLOT_NAME, handle, userId)) {
|
||||
destroyWeaverSlot(handle, userId);
|
||||
}
|
||||
@@ -1352,7 +1352,7 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
}
|
||||
|
||||
private String getHandleName(long handle) {
|
||||
private String getKeyName(long handle) {
|
||||
return String.format("%s%x", LockPatternUtils.SYNTHETIC_PASSWORD_KEY_PREFIX, handle);
|
||||
}
|
||||
|
||||
@@ -1413,4 +1413,19 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
return hexBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate all existing SP keystore keys from uid 1000 app domain to LSS selinux domain
|
||||
*/
|
||||
public boolean migrateKeyNamespace() {
|
||||
boolean success = true;
|
||||
final Map<Integer, List<Long>> allHandles =
|
||||
mStorage.listSyntheticPasswordHandlesForAllUsers(SP_BLOB_NAME);
|
||||
for (List<Long> userHandles : allHandles.values()) {
|
||||
for (long handle : userHandles) {
|
||||
success &= SyntheticPasswordCrypto.migrateLockSettingsKey(getKeyName(handle));
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,8 @@ public class LockSettingsServiceTestable extends LockSettingsService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedProfilePasswordCache getManagedProfilePasswordCache() {
|
||||
public ManagedProfilePasswordCache getManagedProfilePasswordCache(
|
||||
java.security.KeyStore ks) {
|
||||
return mock(ManagedProfilePasswordCache.class);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user