Merge "Revisit the lifetime of the RebootEscrowProvider" am: d746cc814f am: fa83bba5bf
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1678645 Change-Id: I8d476ae93213ff09da715443943482ca436a499f
This commit is contained in:
@@ -205,6 +205,7 @@ class RebootEscrowManager {
|
|||||||
Slog.i(TAG, "Using server based resume on reboot");
|
Slog.i(TAG, "Using server based resume on reboot");
|
||||||
rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage);
|
rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage);
|
||||||
} else {
|
} else {
|
||||||
|
Slog.i(TAG, "Using HAL based resume on reboot");
|
||||||
rebootEscrowProvider = new RebootEscrowProviderHalImpl();
|
rebootEscrowProvider = new RebootEscrowProviderHalImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +240,7 @@ class RebootEscrowManager {
|
|||||||
return mKeyStoreManager;
|
return mKeyStoreManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RebootEscrowProviderInterface getRebootEscrowProvider() {
|
public RebootEscrowProviderInterface createRebootEscrowProviderIfNeeded() {
|
||||||
// Initialize for the provider lazily. Because the device_config and service
|
// Initialize for the provider lazily. Because the device_config and service
|
||||||
// implementation apps may change when system server is running.
|
// implementation apps may change when system server is running.
|
||||||
if (mRebootEscrowProvider == null) {
|
if (mRebootEscrowProvider == null) {
|
||||||
@@ -249,6 +250,14 @@ class RebootEscrowManager {
|
|||||||
return mRebootEscrowProvider;
|
return mRebootEscrowProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RebootEscrowProviderInterface getRebootEscrowProvider() {
|
||||||
|
return mRebootEscrowProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearRebootEscrowProvider() {
|
||||||
|
mRebootEscrowProvider = null;
|
||||||
|
}
|
||||||
|
|
||||||
public int getBootCount() {
|
public int getBootCount() {
|
||||||
return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT,
|
return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT,
|
||||||
0);
|
0);
|
||||||
@@ -308,8 +317,6 @@ class RebootEscrowManager {
|
|||||||
mStorage.removeRebootEscrow(user.id);
|
mStorage.removeRebootEscrow(user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the old key in keystore.
|
|
||||||
mKeyStoreManager.clearKeyStoreEncryptionKey();
|
|
||||||
onEscrowRestoreComplete(false, attemptCount);
|
onEscrowRestoreComplete(false, attemptCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,9 +402,6 @@ class RebootEscrowManager {
|
|||||||
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk);
|
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the old key in keystore. A new key will be generated by new RoR requests.
|
|
||||||
mKeyStoreManager.clearKeyStoreEncryptionKey();
|
|
||||||
|
|
||||||
if (!allUsersUnlocked && mLoadEscrowDataErrorCode == ERROR_NONE) {
|
if (!allUsersUnlocked && mLoadEscrowDataErrorCode == ERROR_NONE) {
|
||||||
mLoadEscrowDataErrorCode = ERROR_UNLOCK_ALL_USERS;
|
mLoadEscrowDataErrorCode = ERROR_UNLOCK_ALL_USERS;
|
||||||
}
|
}
|
||||||
@@ -473,11 +477,17 @@ class RebootEscrowManager {
|
|||||||
if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) {
|
if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) {
|
||||||
reportMetricOnRestoreComplete(success, attemptCount);
|
reportMetricOnRestoreComplete(success, attemptCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the old key in keystore. A new key will be generated by new RoR requests.
|
||||||
|
mKeyStoreManager.clearKeyStoreEncryptionKey();
|
||||||
|
// Clear the saved reboot escrow provider
|
||||||
|
mInjector.clearRebootEscrowProvider();
|
||||||
clearMetricsStorage();
|
clearMetricsStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException {
|
private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException {
|
||||||
RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
|
RebootEscrowProviderInterface rebootEscrowProvider =
|
||||||
|
mInjector.createRebootEscrowProviderIfNeeded();
|
||||||
if (rebootEscrowProvider == null) {
|
if (rebootEscrowProvider == null) {
|
||||||
Slog.w(TAG,
|
Slog.w(TAG,
|
||||||
"Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
|
"Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
|
||||||
@@ -529,9 +539,8 @@ class RebootEscrowManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInjector.getRebootEscrowProvider() == null) {
|
if (mInjector.createRebootEscrowProviderIfNeeded() == null) {
|
||||||
Slog.w(TAG,
|
Slog.w(TAG, "Not storing escrow data, RebootEscrowProvider is unavailable");
|
||||||
"Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,13 +595,17 @@ class RebootEscrowManager {
|
|||||||
mRebootEscrowWanted = false;
|
mRebootEscrowWanted = false;
|
||||||
setRebootEscrowReady(false);
|
setRebootEscrowReady(false);
|
||||||
|
|
||||||
RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
|
// We want to clear the internal data inside the provider, so always try to create the
|
||||||
|
// provider.
|
||||||
|
RebootEscrowProviderInterface rebootEscrowProvider =
|
||||||
|
mInjector.createRebootEscrowProviderIfNeeded();
|
||||||
if (rebootEscrowProvider == null) {
|
if (rebootEscrowProvider == null) {
|
||||||
Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request");
|
Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request");
|
||||||
} else {
|
} else {
|
||||||
rebootEscrowProvider.clearRebootEscrowKey();
|
rebootEscrowProvider.clearRebootEscrowKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mInjector.clearRebootEscrowProvider();
|
||||||
clearMetricsStorage();
|
clearMetricsStorage();
|
||||||
|
|
||||||
List<UserInfo> users = mUserManager.getUsers();
|
List<UserInfo> users = mUserManager.getUsers();
|
||||||
@@ -610,8 +623,7 @@ class RebootEscrowManager {
|
|||||||
|
|
||||||
RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
|
RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
|
||||||
if (rebootEscrowProvider == null) {
|
if (rebootEscrowProvider == null) {
|
||||||
Slog.w(TAG,
|
Slog.w(TAG, "Not storing escrow key, RebootEscrowProvider is unavailable");
|
||||||
"Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
|
|
||||||
clearRebootEscrowIfNeeded();
|
clearRebootEscrowIfNeeded();
|
||||||
return ARM_REBOOT_ERROR_NO_PROVIDER;
|
return ARM_REBOOT_ERROR_NO_PROVIDER;
|
||||||
}
|
}
|
||||||
@@ -677,11 +689,12 @@ class RebootEscrowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean prepareRebootEscrow() {
|
boolean prepareRebootEscrow() {
|
||||||
if (mInjector.getRebootEscrowProvider() == null) {
|
clearRebootEscrowIfNeeded();
|
||||||
|
if (mInjector.createRebootEscrowProviderIfNeeded() == null) {
|
||||||
|
Slog.w(TAG, "No reboot escrow provider, skipping resume on reboot preparation.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearRebootEscrowIfNeeded();
|
|
||||||
mRebootEscrowWanted = true;
|
mRebootEscrowWanted = true;
|
||||||
mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF);
|
mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF);
|
||||||
return true;
|
return true;
|
||||||
@@ -807,6 +820,10 @@ class RebootEscrowManager {
|
|||||||
pw.print("mPendingRebootEscrowKey is ");
|
pw.print("mPendingRebootEscrowKey is ");
|
||||||
pw.println(keySet ? "set" : "not set");
|
pw.println(keySet ? "set" : "not set");
|
||||||
|
|
||||||
|
RebootEscrowProviderInterface provider = mInjector.getRebootEscrowProvider();
|
||||||
|
String providerType = provider == null ? "null" : String.valueOf(provider.getType());
|
||||||
|
pw.print("RebootEscrowProvider type is " + providerType);
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.println("Event log:");
|
pw.println("Event log:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
|
|||||||
@@ -112,14 +112,13 @@ public class RebootEscrowManagerTests {
|
|||||||
private MockableRebootEscrowInjected mInjected;
|
private MockableRebootEscrowInjected mInjected;
|
||||||
private RebootEscrowManager mService;
|
private RebootEscrowManager mService;
|
||||||
private SecretKey mAesKey;
|
private SecretKey mAesKey;
|
||||||
|
private MockInjector mMockInjector;
|
||||||
|
|
||||||
public interface MockableRebootEscrowInjected {
|
public interface MockableRebootEscrowInjected {
|
||||||
int getBootCount();
|
int getBootCount();
|
||||||
|
|
||||||
long getCurrentTimeMillis();
|
long getCurrentTimeMillis();
|
||||||
|
|
||||||
boolean forceServerBased();
|
|
||||||
|
|
||||||
void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount,
|
void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount,
|
||||||
int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootComplete);
|
int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootComplete);
|
||||||
}
|
}
|
||||||
@@ -127,11 +126,12 @@ public class RebootEscrowManagerTests {
|
|||||||
static class MockInjector extends RebootEscrowManager.Injector {
|
static class MockInjector extends RebootEscrowManager.Injector {
|
||||||
private final IRebootEscrow mRebootEscrow;
|
private final IRebootEscrow mRebootEscrow;
|
||||||
private final ResumeOnRebootServiceConnection mServiceConnection;
|
private final ResumeOnRebootServiceConnection mServiceConnection;
|
||||||
private final RebootEscrowProviderInterface mRebootEscrowProvider;
|
private final RebootEscrowProviderInterface mDefaultRebootEscrowProvider;
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final MockableRebootEscrowInjected mInjected;
|
private final MockableRebootEscrowInjected mInjected;
|
||||||
private final RebootEscrowKeyStoreManager mKeyStoreManager;
|
private final RebootEscrowKeyStoreManager mKeyStoreManager;
|
||||||
private final boolean mServerBased;
|
private boolean mServerBased;
|
||||||
|
private RebootEscrowProviderInterface mRebootEscrowProviderInUse;
|
||||||
|
|
||||||
MockInjector(Context context, UserManager userManager,
|
MockInjector(Context context, UserManager userManager,
|
||||||
IRebootEscrow rebootEscrow,
|
IRebootEscrow rebootEscrow,
|
||||||
@@ -149,7 +149,7 @@ public class RebootEscrowManagerTests {
|
|||||||
return mRebootEscrow;
|
return mRebootEscrow;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector);
|
mDefaultRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector);
|
||||||
mUserManager = userManager;
|
mUserManager = userManager;
|
||||||
mKeyStoreManager = keyStoreManager;
|
mKeyStoreManager = keyStoreManager;
|
||||||
mInjected = injected;
|
mInjected = injected;
|
||||||
@@ -166,7 +166,8 @@ public class RebootEscrowManagerTests {
|
|||||||
mServerBased = true;
|
mServerBased = true;
|
||||||
RebootEscrowProviderServerBasedImpl.Injector injector =
|
RebootEscrowProviderServerBasedImpl.Injector injector =
|
||||||
new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection);
|
new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection);
|
||||||
mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(storage, injector);
|
mDefaultRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(
|
||||||
|
storage, injector);
|
||||||
mUserManager = userManager;
|
mUserManager = userManager;
|
||||||
mKeyStoreManager = keyStoreManager;
|
mKeyStoreManager = keyStoreManager;
|
||||||
mInjected = injected;
|
mInjected = injected;
|
||||||
@@ -184,15 +185,23 @@ public class RebootEscrowManagerTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean serverBasedResumeOnReboot() {
|
public boolean serverBasedResumeOnReboot() {
|
||||||
if (mInjected.forceServerBased()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return mServerBased;
|
return mServerBased;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RebootEscrowProviderInterface createRebootEscrowProviderIfNeeded() {
|
||||||
|
mRebootEscrowProviderInUse = mDefaultRebootEscrowProvider;
|
||||||
|
return mRebootEscrowProviderInUse;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RebootEscrowProviderInterface getRebootEscrowProvider() {
|
public RebootEscrowProviderInterface getRebootEscrowProvider() {
|
||||||
return mRebootEscrowProvider;
|
return mRebootEscrowProviderInUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearRebootEscrowProvider() {
|
||||||
|
mRebootEscrowProviderInUse = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -264,13 +273,15 @@ public class RebootEscrowManagerTests {
|
|||||||
when(mCallbacks.isUserSecure(NONSECURE_SECONDARY_USER_ID)).thenReturn(false);
|
when(mCallbacks.isUserSecure(NONSECURE_SECONDARY_USER_ID)).thenReturn(false);
|
||||||
when(mCallbacks.isUserSecure(SECURE_SECONDARY_USER_ID)).thenReturn(true);
|
when(mCallbacks.isUserSecure(SECURE_SECONDARY_USER_ID)).thenReturn(true);
|
||||||
mInjected = mock(MockableRebootEscrowInjected.class);
|
mInjected = mock(MockableRebootEscrowInjected.class);
|
||||||
mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager, mRebootEscrow,
|
mMockInjector = new MockInjector(mContext, mUserManager, mRebootEscrow,
|
||||||
mKeyStoreManager, mStorage, mInjected), mCallbacks, mStorage);
|
mKeyStoreManager, mStorage, mInjected);
|
||||||
|
mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setServerBasedRebootEscrowProvider() throws Exception {
|
private void setServerBasedRebootEscrowProvider() throws Exception {
|
||||||
mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager,
|
mMockInjector = new MockInjector(mContext, mUserManager, mServiceConnection,
|
||||||
mServiceConnection, mKeyStoreManager, mStorage, mInjected), mCallbacks, mStorage);
|
mKeyStoreManager, mStorage, mInjected);
|
||||||
|
mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -317,6 +328,7 @@ public class RebootEscrowManagerTests {
|
|||||||
doThrow(ServiceSpecificException.class).when(mRebootEscrow).storeKey(any());
|
doThrow(ServiceSpecificException.class).when(mRebootEscrow).storeKey(any());
|
||||||
mService.clearRebootEscrow();
|
mService.clearRebootEscrow();
|
||||||
verify(mRebootEscrow).storeKey(eq(new byte[32]));
|
verify(mRebootEscrow).storeKey(eq(new byte[32]));
|
||||||
|
assertNull(mMockInjector.getRebootEscrowProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -785,7 +797,7 @@ public class RebootEscrowManagerTests {
|
|||||||
assertNull(
|
assertNull(
|
||||||
mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM));
|
mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM));
|
||||||
// Change the provider to server based, expect the reboot to fail
|
// Change the provider to server based, expect the reboot to fail
|
||||||
when(mInjected.forceServerBased()).thenReturn(true);
|
mMockInjector.mServerBased = true;
|
||||||
assertEquals(ARM_REBOOT_ERROR_PROVIDER_MISMATCH, mService.armRebootEscrowIfNeeded());
|
assertEquals(ARM_REBOOT_ERROR_PROVIDER_MISMATCH, mService.armRebootEscrowIfNeeded());
|
||||||
assertNull(
|
assertNull(
|
||||||
mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM));
|
mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM));
|
||||||
|
|||||||
Reference in New Issue
Block a user