summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java6
-rw-r--r--services/core/java/com/android/server/locksettings/RebootEscrowManager.java144
2 files changed, 150 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1b4ec8a8fa32..01af83914800 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -3193,6 +3193,12 @@ public class LockSettingsService extends ILockSettings.Stub {
mStrongAuth.dump(pw);
pw.println();
pw.decreaseIndent();
+
+ pw.println("RebootEscrow:");
+ pw.increaseIndent();
+ mRebootEscrowManager.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
}
/**
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index dabf88670639..8d4efed8604b 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -18,6 +18,7 @@ package com.android.server.locksettings;
import static android.os.UserHandle.USER_SYSTEM;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
@@ -25,6 +26,7 @@ import android.content.pm.UserInfo;
import android.hardware.rebootescrow.IRebootEscrow;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
@@ -32,11 +34,15 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.widget.RebootEscrowListener;
import java.io.IOException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
+import java.util.Locale;
import java.util.NoSuchElementException;
class RebootEscrowManager {
@@ -63,6 +69,11 @@ class RebootEscrowManager {
private static final int BOOT_COUNT_TOLERANCE = 5;
/**
+ * Logs events for later debugging in bugreports.
+ */
+ private final RebootEscrowEventLog mEventLog;
+
+ /**
* Used to track when the reboot escrow is wanted. Should stay true once escrow is requested
* unless clearRebootEscrow is called. This will allow all the active users to be unlocked
* after reboot.
@@ -135,6 +146,10 @@ class RebootEscrowManager {
public void reportMetric(boolean success) {
FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success);
}
+
+ public RebootEscrowEventLog getEventLog() {
+ return new RebootEscrowEventLog();
+ }
}
RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) {
@@ -148,6 +163,7 @@ class RebootEscrowManager {
mCallbacks = callbacks;
mStorage = storage;
mUserManager = injector.getUserManager();
+ mEventLog = injector.getEventLog();
}
void loadRebootEscrowDataIfAvailable() {
@@ -173,6 +189,8 @@ class RebootEscrowManager {
return;
}
+ mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA);
+
boolean allUsersUnlocked = true;
for (UserInfo user : rebootEscrowUsers) {
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey);
@@ -221,6 +239,7 @@ class RebootEscrowManager {
// Overwrite the existing key with the null key
rebootEscrow.storeKey(new byte[32]);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
} catch (RemoteException e) {
Slog.w(TAG, "Could not retrieve escrow data");
@@ -242,6 +261,7 @@ class RebootEscrowManager {
mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
escrowData.getSyntheticPassword(), userId);
Slog.i(TAG, "Restored reboot escrow data for user " + userId);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId);
return true;
} catch (IOException e) {
Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
@@ -278,6 +298,7 @@ class RebootEscrowManager {
}
mStorage.writeRebootEscrow(userId, escrowData.getBlob());
+ mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId);
setRebootEscrowReady(true);
}
@@ -322,6 +343,8 @@ class RebootEscrowManager {
for (UserInfo user : users) {
mStorage.removeRebootEscrow(user.id);
}
+
+ mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST);
}
boolean armRebootEscrowIfNeeded() {
@@ -356,6 +379,7 @@ class RebootEscrowManager {
if (armedRebootEscrow) {
mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
+ mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
}
return armedRebootEscrow;
@@ -375,6 +399,7 @@ class RebootEscrowManager {
clearRebootEscrowIfNeeded();
mRebootEscrowWanted = true;
+ mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF);
return true;
}
@@ -390,4 +415,123 @@ class RebootEscrowManager {
void setRebootEscrowListener(RebootEscrowListener listener) {
mRebootEscrowListener = listener;
}
+
+ @VisibleForTesting
+ public static class RebootEscrowEvent {
+ static final int FOUND_ESCROW_DATA = 1;
+ static final int SET_ARMED_STATUS = 2;
+ static final int CLEARED_LSKF_REQUEST = 3;
+ static final int RETRIEVED_STORED_KEK = 4;
+ static final int REQUESTED_LSKF = 5;
+ static final int STORED_LSKF_FOR_USER = 6;
+ static final int RETRIEVED_LSKF_FOR_USER = 7;
+
+ final int mEventId;
+ final Integer mUserId;
+ final long mWallTime;
+ final long mTimestamp;
+
+ RebootEscrowEvent(int eventId) {
+ this(eventId, null);
+ }
+
+ RebootEscrowEvent(int eventId, Integer userId) {
+ mEventId = eventId;
+ mUserId = userId;
+ mTimestamp = SystemClock.uptimeMillis();
+ mWallTime = System.currentTimeMillis();
+ }
+
+ String getEventDescription() {
+ switch (mEventId) {
+ case FOUND_ESCROW_DATA:
+ return "Found escrow data";
+ case SET_ARMED_STATUS:
+ return "Set armed status";
+ case CLEARED_LSKF_REQUEST:
+ return "Cleared request for LSKF";
+ case RETRIEVED_STORED_KEK:
+ return "Retrieved stored KEK";
+ case REQUESTED_LSKF:
+ return "Requested LSKF";
+ case STORED_LSKF_FOR_USER:
+ return "Stored LSKF for user";
+ case RETRIEVED_LSKF_FOR_USER:
+ return "Retrieved LSKF for user";
+ default:
+ return "Unknown event ID " + mEventId;
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public static class RebootEscrowEventLog {
+ private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16];
+ private int mNextIndex = 0;
+
+ void addEntry(int eventId) {
+ addEntryInternal(new RebootEscrowEvent(eventId));
+ }
+
+ void addEntry(int eventId, int userId) {
+ addEntryInternal(new RebootEscrowEvent(eventId, userId));
+ }
+
+ private void addEntryInternal(RebootEscrowEvent event) {
+ final int index = mNextIndex;
+ mEntries[index] = event;
+ mNextIndex = (mNextIndex + 1) % mEntries.length;
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
+
+ for (int i = 0; i < mEntries.length; ++i) {
+ RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length];
+ if (event == null) {
+ continue;
+ }
+
+ pw.print("Event #");
+ pw.println(i);
+
+ pw.println(" time=" + sdf.format(new Date(event.mWallTime))
+ + " (timestamp=" + event.mTimestamp + ")");
+
+ pw.print(" event=");
+ pw.println(event.getEventDescription());
+
+ if (event.mUserId != null) {
+ pw.print(" user=");
+ pw.println(event.mUserId);
+ }
+ }
+ }
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ pw.print("mRebootEscrowWanted=");
+ pw.println(mRebootEscrowWanted);
+
+ pw.print("mRebootEscrowReady=");
+ pw.println(mRebootEscrowReady);
+
+ pw.print("mRebootEscrowListener=");
+ pw.println(mRebootEscrowListener);
+
+ boolean keySet;
+ synchronized (mKeyGenerationLock) {
+ keySet = mPendingRebootEscrowKey != null;
+ }
+
+ pw.print("mPendingRebootEscrowKey is ");
+ pw.println(keySet ? "set" : "not set");
+
+ pw.println();
+ pw.println("Event log:");
+ pw.increaseIndent();
+ mEventLog.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
+ }
}