1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.locksettings; 18 19 import static android.os.UserHandle.USER_SYSTEM; 20 21 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY; 22 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE; 23 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; 24 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY; 25 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER; 26 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH; 27 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_STORE_ESCROW_KEY; 28 import static com.android.internal.widget.LockSettingsInternal.ArmRebootEscrowErrorCode; 29 30 import android.annotation.IntDef; 31 import android.annotation.NonNull; 32 import android.annotation.UserIdInt; 33 import android.content.Context; 34 import android.content.pm.PackageManager; 35 import android.content.pm.UserInfo; 36 import android.net.ConnectivityManager; 37 import android.net.Network; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkRequest; 40 import android.os.Handler; 41 import android.os.PowerManager; 42 import android.os.SystemClock; 43 import android.os.SystemProperties; 44 import android.os.UserManager; 45 import android.provider.DeviceConfig; 46 import android.provider.Settings; 47 import android.util.Slog; 48 49 import com.android.internal.annotations.GuardedBy; 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.util.FrameworkStatsLog; 52 import com.android.internal.util.IndentingPrintWriter; 53 import com.android.internal.widget.RebootEscrowListener; 54 import com.android.server.pm.UserManagerInternal; 55 56 import java.io.IOException; 57 import java.lang.annotation.Retention; 58 import java.lang.annotation.RetentionPolicy; 59 import java.text.SimpleDateFormat; 60 import java.util.ArrayList; 61 import java.util.Collections; 62 import java.util.Date; 63 import java.util.HashSet; 64 import java.util.List; 65 import java.util.Locale; 66 import java.util.Objects; 67 import java.util.Set; 68 69 import javax.crypto.SecretKey; 70 71 /** 72 * This class aims to persists the synthetic password(SP) across reboot in a secure way. In 73 * particular, it manages the encryption of the sp before reboot, and decryption of the sp after 74 * reboot. Here are the meaning of some terms. 75 * SP: synthetic password 76 * K_s: The RebootEscrowKey, i.e. AES-GCM key stored in memory 77 * K_k: AES-GCM key in android keystore 78 * RebootEscrowData: The synthetic password and its encrypted blob. We encrypt SP with K_s first, 79 * then with K_k, i.e. E(K_k, E(K_s, SP)) 80 */ 81 class RebootEscrowManager { 82 private static final String TAG = "RebootEscrowManager"; 83 84 /** 85 * Used in the database storage to indicate the boot count at which the reboot escrow was 86 * previously armed. 87 */ 88 @VisibleForTesting 89 public static final String REBOOT_ESCROW_ARMED_KEY = "reboot_escrow_armed_count"; 90 91 static final String REBOOT_ESCROW_KEY_ARMED_TIMESTAMP = "reboot_escrow_key_stored_timestamp"; 92 static final String REBOOT_ESCROW_KEY_PROVIDER = "reboot_escrow_key_provider"; 93 94 /** 95 * The verified boot 2.0 vbmeta digest of the current slot, the property value is always 96 * available after boot. 97 */ 98 static final String VBMETA_DIGEST_PROP_NAME = "ro.boot.vbmeta.digest"; 99 /** 100 * The system prop contains vbmeta digest of the inactive slot. The build property is set after 101 * an OTA update. RebootEscrowManager will store it in disk before the OTA reboot, so the value 102 * is available for vbmeta digest verification after the device reboots. 103 */ 104 static final String OTHER_VBMETA_DIGEST_PROP_NAME = "ota.other.vbmeta_digest"; 105 static final String REBOOT_ESCROW_KEY_VBMETA_DIGEST = "reboot_escrow_key_vbmeta_digest"; 106 static final String REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST = 107 "reboot_escrow_key_other_vbmeta_digest"; 108 109 /** 110 * Number of boots until we consider the escrow data to be stale for the purposes of metrics. 111 * 112 * <p>If the delta between the current boot number and the boot number stored when the mechanism 113 * was armed is under this number and the escrow mechanism fails, we report it as a failure of 114 * the mechanism. 115 * 116 * <p>If the delta over this number and escrow fails, we will not report the metric as failed 117 * since there most likely was some other issue if the device rebooted several times before 118 * getting to the escrow restore code. 119 */ 120 private static final int BOOT_COUNT_TOLERANCE = 5; 121 122 /** 123 * The default retry specs for loading reboot escrow data. We will attempt to retry loading 124 * escrow data on temporarily errors, e.g. unavailable network. 125 */ 126 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3; 127 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30; 128 129 // 3 minutes. It's enough for the default 3 retries with 30 seconds interval 130 private static final int DEFAULT_LOAD_ESCROW_BASE_TIMEOUT_MILLIS = 180_000; 131 // 5 seconds. An extension of the overall RoR timeout to account for overhead. 132 private static final int DEFAULT_LOAD_ESCROW_TIMEOUT_EXTENSION_MILLIS = 5000; 133 134 @IntDef(prefix = {"ERROR_"}, value = { 135 ERROR_NONE, 136 ERROR_UNKNOWN, 137 ERROR_NO_PROVIDER, 138 ERROR_LOAD_ESCROW_KEY, 139 ERROR_RETRY_COUNT_EXHAUSTED, 140 ERROR_UNLOCK_ALL_USERS, 141 ERROR_PROVIDER_MISMATCH, 142 ERROR_KEYSTORE_FAILURE, 143 ERROR_NO_NETWORK, 144 ERROR_TIMEOUT_EXHAUSTED, 145 }) 146 @Retention(RetentionPolicy.SOURCE) 147 @interface RebootEscrowErrorCode { 148 } 149 150 static final int ERROR_NONE = 0; 151 static final int ERROR_UNKNOWN = 1; 152 static final int ERROR_NO_PROVIDER = 2; 153 static final int ERROR_LOAD_ESCROW_KEY = 3; 154 static final int ERROR_RETRY_COUNT_EXHAUSTED = 4; 155 static final int ERROR_UNLOCK_ALL_USERS = 5; 156 static final int ERROR_PROVIDER_MISMATCH = 6; 157 static final int ERROR_KEYSTORE_FAILURE = 7; 158 static final int ERROR_NO_NETWORK = 8; 159 static final int ERROR_TIMEOUT_EXHAUSTED = 9; 160 161 private @RebootEscrowErrorCode int mLoadEscrowDataErrorCode = ERROR_NONE; 162 163 /** 164 * Logs events for later debugging in bugreports. 165 */ 166 private final RebootEscrowEventLog mEventLog; 167 168 /** 169 * Used to track when the reboot escrow is wanted. Should stay true once escrow is requested 170 * unless clearRebootEscrow is called. This will allow all the active users to be unlocked 171 * after reboot. 172 */ 173 private boolean mRebootEscrowWanted; 174 175 /** Used to track when reboot escrow is ready. */ 176 private boolean mRebootEscrowReady; 177 178 /** Notified when mRebootEscrowReady changes. */ 179 private RebootEscrowListener mRebootEscrowListener; 180 181 /** Set when unlocking reboot escrow times out. */ 182 private boolean mRebootEscrowTimedOut = false; 183 184 /** 185 * Set when {@link #loadRebootEscrowDataWithRetry} is called to ensure the function is only 186 * called once. 187 */ 188 private boolean mLoadEscrowDataWithRetry = false; 189 190 /** 191 * Hold this lock when checking or generating the reboot escrow key. 192 */ 193 private final Object mKeyGenerationLock = new Object(); 194 195 /** 196 * Stores the reboot escrow data between when it's supplied and when 197 * {@link #armRebootEscrowIfNeeded()} is called. 198 */ 199 @GuardedBy("mKeyGenerationLock") 200 private RebootEscrowKey mPendingRebootEscrowKey; 201 202 private final UserManager mUserManager; 203 204 private final Injector mInjector; 205 206 private final LockSettingsStorage mStorage; 207 208 private final Callbacks mCallbacks; 209 210 private final RebootEscrowKeyStoreManager mKeyStoreManager; 211 212 private final Handler mHandler; 213 214 PowerManager.WakeLock mWakeLock; 215 216 private ConnectivityManager.NetworkCallback mNetworkCallback; 217 218 interface Callbacks { isUserSecure(int userId)219 boolean isUserSecure(int userId); 220 onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId)221 void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId); 222 } 223 224 static class Injector { 225 protected Context mContext; 226 private final RebootEscrowKeyStoreManager mKeyStoreManager; 227 private final LockSettingsStorage mStorage; 228 private RebootEscrowProviderInterface mRebootEscrowProvider; 229 private final UserManagerInternal mUserManagerInternal; 230 Injector( Context context, LockSettingsStorage storage, UserManagerInternal userManagerInternal)231 Injector( 232 Context context, 233 LockSettingsStorage storage, 234 UserManagerInternal userManagerInternal) { 235 mContext = context; 236 mStorage = storage; 237 mKeyStoreManager = new RebootEscrowKeyStoreManager(); 238 mUserManagerInternal = userManagerInternal; 239 } 240 createRebootEscrowProvider()241 private RebootEscrowProviderInterface createRebootEscrowProvider() { 242 RebootEscrowProviderInterface rebootEscrowProvider; 243 if (serverBasedResumeOnReboot()) { 244 Slog.i(TAG, "Using server based resume on reboot"); 245 rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage); 246 } else { 247 Slog.i(TAG, "Using HAL based resume on reboot"); 248 rebootEscrowProvider = new RebootEscrowProviderHalImpl(); 249 } 250 251 if (rebootEscrowProvider.hasRebootEscrowSupport()) { 252 return rebootEscrowProvider; 253 } 254 return null; 255 } 256 post(Handler handler, Runnable runnable)257 void post(Handler handler, Runnable runnable) { 258 handler.post(runnable); 259 } 260 postDelayed(Handler handler, Runnable runnable, long delayMillis)261 void postDelayed(Handler handler, Runnable runnable, long delayMillis) { 262 handler.postDelayed(runnable, delayMillis); 263 } 264 serverBasedResumeOnReboot()265 public boolean serverBasedResumeOnReboot() { 266 // Always use the server based RoR if the HAL isn't installed on device. 267 if (!mContext.getPackageManager().hasSystemFeature( 268 PackageManager.FEATURE_REBOOT_ESCROW)) { 269 return true; 270 } 271 272 return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, 273 "server_based_ror_enabled", false); 274 } 275 isNetworkConnected()276 public boolean isNetworkConnected() { 277 final ConnectivityManager connectivityManager = 278 mContext.getSystemService(ConnectivityManager.class); 279 if (connectivityManager == null) { 280 return false; 281 } 282 283 Network activeNetwork = connectivityManager.getActiveNetwork(); 284 NetworkCapabilities networkCapabilities = 285 connectivityManager.getNetworkCapabilities(activeNetwork); 286 return networkCapabilities != null 287 && networkCapabilities.hasCapability( 288 NetworkCapabilities.NET_CAPABILITY_INTERNET) 289 && networkCapabilities.hasCapability( 290 NetworkCapabilities.NET_CAPABILITY_VALIDATED); 291 } 292 293 /** 294 * Request network with internet connectivity with timeout. 295 * 296 * @param networkCallback callback to be executed if connectivity manager exists. 297 * @return true if success 298 */ requestNetworkWithInternet( ConnectivityManager.NetworkCallback networkCallback)299 public boolean requestNetworkWithInternet( 300 ConnectivityManager.NetworkCallback networkCallback) { 301 final ConnectivityManager connectivityManager = 302 mContext.getSystemService(ConnectivityManager.class); 303 if (connectivityManager == null) { 304 return false; 305 } 306 NetworkRequest request = 307 new NetworkRequest.Builder() 308 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 309 .build(); 310 311 connectivityManager.requestNetwork( 312 request, networkCallback, getLoadEscrowTimeoutMillis()); 313 return true; 314 } 315 stopRequestingNetwork(ConnectivityManager.NetworkCallback networkCallback)316 public void stopRequestingNetwork(ConnectivityManager.NetworkCallback networkCallback) { 317 final ConnectivityManager connectivityManager = 318 mContext.getSystemService(ConnectivityManager.class); 319 if (connectivityManager == null) { 320 return; 321 } 322 connectivityManager.unregisterNetworkCallback(networkCallback); 323 } 324 getContext()325 public Context getContext() { 326 return mContext; 327 } 328 getUserManager()329 public UserManager getUserManager() { 330 return (UserManager) mContext.getSystemService(Context.USER_SERVICE); 331 } 332 getUserManagerInternal()333 public UserManagerInternal getUserManagerInternal() { 334 return mUserManagerInternal; 335 } 336 getKeyStoreManager()337 public RebootEscrowKeyStoreManager getKeyStoreManager() { 338 return mKeyStoreManager; 339 } 340 createRebootEscrowProviderIfNeeded()341 public RebootEscrowProviderInterface createRebootEscrowProviderIfNeeded() { 342 // Initialize for the provider lazily. Because the device_config and service 343 // implementation apps may change when system server is running. 344 if (mRebootEscrowProvider == null) { 345 mRebootEscrowProvider = createRebootEscrowProvider(); 346 } 347 348 return mRebootEscrowProvider; 349 } 350 getWakeLock()351 PowerManager.WakeLock getWakeLock() { 352 final PowerManager pm = mContext.getSystemService(PowerManager.class); 353 return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RebootEscrowManager"); 354 } 355 getRebootEscrowProvider()356 public RebootEscrowProviderInterface getRebootEscrowProvider() { 357 return mRebootEscrowProvider; 358 } 359 clearRebootEscrowProvider()360 public void clearRebootEscrowProvider() { 361 mRebootEscrowProvider = null; 362 } 363 getBootCount()364 public int getBootCount() { 365 return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 366 0); 367 } 368 getCurrentTimeMillis()369 public long getCurrentTimeMillis() { 370 return System.currentTimeMillis(); 371 } 372 getLoadEscrowDataRetryLimit()373 public int getLoadEscrowDataRetryLimit() { 374 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 375 "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT); 376 } 377 getLoadEscrowDataRetryIntervalSeconds()378 public int getLoadEscrowDataRetryIntervalSeconds() { 379 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 380 "load_escrow_data_retry_interval_seconds", 381 DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS); 382 } 383 384 @VisibleForTesting getLoadEscrowTimeoutMillis()385 public int getLoadEscrowTimeoutMillis() { 386 return DEFAULT_LOAD_ESCROW_BASE_TIMEOUT_MILLIS; 387 } 388 389 @VisibleForTesting getWakeLockTimeoutMillis()390 public int getWakeLockTimeoutMillis() { 391 return getLoadEscrowTimeoutMillis() + DEFAULT_LOAD_ESCROW_TIMEOUT_EXTENSION_MILLIS; 392 } 393 reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootCompleteInSeconds)394 public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, 395 int escrowDurationInSeconds, int vbmetaDigestStatus, 396 int durationSinceBootCompleteInSeconds) { 397 FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success, 398 errorCode, serviceType, attemptCount, escrowDurationInSeconds, 399 vbmetaDigestStatus, durationSinceBootCompleteInSeconds); 400 } 401 getEventLog()402 public RebootEscrowEventLog getEventLog() { 403 return new RebootEscrowEventLog(); 404 } 405 getVbmetaDigest(boolean other)406 public String getVbmetaDigest(boolean other) { 407 return other ? SystemProperties.get(OTHER_VBMETA_DIGEST_PROP_NAME) 408 : SystemProperties.get(VBMETA_DIGEST_PROP_NAME); 409 } 410 } 411 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage, Handler handler, UserManagerInternal userManagerInternal)412 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage, 413 Handler handler, UserManagerInternal userManagerInternal) { 414 this(new Injector(context, storage, userManagerInternal), callbacks, storage, handler); 415 } 416 417 @VisibleForTesting RebootEscrowManager(Injector injector, Callbacks callbacks, LockSettingsStorage storage, Handler handler)418 RebootEscrowManager(Injector injector, Callbacks callbacks, 419 LockSettingsStorage storage, Handler handler) { 420 mInjector = injector; 421 mCallbacks = callbacks; 422 mStorage = storage; 423 mUserManager = injector.getUserManager(); 424 mEventLog = injector.getEventLog(); 425 mKeyStoreManager = injector.getKeyStoreManager(); 426 mHandler = handler; 427 } 428 429 /** Wrapper function to set error code serialized through handler, */ setLoadEscrowDataErrorCode(@ebootEscrowErrorCode int value, Handler handler)430 private void setLoadEscrowDataErrorCode(@RebootEscrowErrorCode int value, Handler handler) { 431 mInjector.post( 432 handler, 433 () -> { 434 mLoadEscrowDataErrorCode = value; 435 }); 436 } 437 438 /** Wrapper function to compare and set error code serialized through handler. */ compareAndSetLoadEscrowDataErrorCode( @ebootEscrowErrorCode int expectedValue, @RebootEscrowErrorCode int newValue, Handler handler)439 private void compareAndSetLoadEscrowDataErrorCode( 440 @RebootEscrowErrorCode int expectedValue, 441 @RebootEscrowErrorCode int newValue, 442 Handler handler) { 443 if (expectedValue == mLoadEscrowDataErrorCode) { 444 setLoadEscrowDataErrorCode(newValue, handler); 445 } 446 } 447 onGetRebootEscrowKeyFailed( List<UserInfo> users, int attemptCount, Handler retryHandler)448 private void onGetRebootEscrowKeyFailed( 449 List<UserInfo> users, int attemptCount, Handler retryHandler) { 450 Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); 451 for (UserInfo user : users) { 452 mStorage.removeRebootEscrow(user.id); 453 } 454 455 onEscrowRestoreComplete(false, attemptCount, retryHandler); 456 } 457 getUsersToUnlock(List<UserInfo> users)458 private List<UserInfo> getUsersToUnlock(List<UserInfo> users) { 459 // System user must be unlocked to unlock any other user 460 if (mCallbacks.isUserSecure(USER_SYSTEM) && !mStorage.hasRebootEscrow(USER_SYSTEM)) { 461 Slog.i(TAG, "No reboot escrow data found for system user"); 462 return Collections.emptyList(); 463 } 464 465 Set<Integer> noEscrowDataUsers = new HashSet<>(); 466 for (UserInfo user : users) { 467 if (mCallbacks.isUserSecure(user.id) 468 && !mStorage.hasRebootEscrow(user.id)) { 469 Slog.d(TAG, "No reboot escrow data found for user " + user); 470 noEscrowDataUsers.add(user.id); 471 } 472 } 473 474 List<UserInfo> rebootEscrowUsers = new ArrayList<>(); 475 for (UserInfo user : users) { 476 // No lskf, no need to unlock. 477 if (!mCallbacks.isUserSecure(user.id)) { 478 continue; 479 } 480 // Don't unlock if user or user's parent does not have reboot data 481 int userId = user.id; 482 if (noEscrowDataUsers.contains(userId) 483 || noEscrowDataUsers.contains( 484 mInjector.getUserManagerInternal().getProfileParentId(userId))) { 485 continue; 486 } 487 rebootEscrowUsers.add(user); 488 } 489 return rebootEscrowUsers; 490 } 491 loadRebootEscrowDataIfAvailable(Handler retryHandler)492 void loadRebootEscrowDataIfAvailable(Handler retryHandler) { 493 List<UserInfo> users = mUserManager.getUsers(); 494 List<UserInfo> rebootEscrowUsers = getUsersToUnlock(users); 495 496 if (rebootEscrowUsers.isEmpty()) { 497 Slog.i(TAG, "No reboot escrow data found for users," 498 + " skipping loading escrow data"); 499 clearMetricsStorage(); 500 return; 501 } 502 503 // Acquire the wake lock to make sure our scheduled task will run. 504 mWakeLock = mInjector.getWakeLock(); 505 if (mWakeLock != null) { 506 mWakeLock.setReferenceCounted(false); 507 mWakeLock.acquire(mInjector.getWakeLockTimeoutMillis()); 508 } 509 510 // Timeout to stop retrying same as the wake lock timeout. 511 mInjector.postDelayed( 512 retryHandler, 513 () -> { 514 mRebootEscrowTimedOut = true; 515 }, 516 mInjector.getLoadEscrowTimeoutMillis()); 517 518 mInjector.post( 519 retryHandler, 520 () -> loadRebootEscrowDataOnInternet(retryHandler, users, rebootEscrowUsers)); 521 } 522 scheduleLoadRebootEscrowDataOrFail( Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)523 void scheduleLoadRebootEscrowDataOrFail( 524 Handler retryHandler, 525 int attemptNumber, 526 List<UserInfo> users, 527 List<UserInfo> rebootEscrowUsers) { 528 Objects.requireNonNull(retryHandler); 529 530 final int retryLimit = mInjector.getLoadEscrowDataRetryLimit(); 531 final int retryIntervalInSeconds = mInjector.getLoadEscrowDataRetryIntervalSeconds(); 532 533 if (attemptNumber < retryLimit && !mRebootEscrowTimedOut) { 534 Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber); 535 mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry( 536 retryHandler, attemptNumber, users, rebootEscrowUsers), 537 retryIntervalInSeconds * 1000); 538 return; 539 } 540 541 if (mRebootEscrowTimedOut) { 542 Slog.w(TAG, "Failed to load reboot escrow data within timeout"); 543 compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_TIMEOUT_EXHAUSTED, retryHandler); 544 } else { 545 Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); 546 compareAndSetLoadEscrowDataErrorCode( 547 ERROR_NONE, ERROR_RETRY_COUNT_EXHAUSTED, retryHandler); 548 } 549 onGetRebootEscrowKeyFailed(users, attemptNumber, retryHandler); 550 } 551 loadRebootEscrowDataOnInternet( Handler retryHandler, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)552 void loadRebootEscrowDataOnInternet( 553 Handler retryHandler, List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { 554 555 // HAL-Based RoR does not require network connectivity. 556 if (!mInjector.serverBasedResumeOnReboot()) { 557 loadRebootEscrowDataWithRetry( 558 retryHandler, /* attemptNumber = */ 0, users, rebootEscrowUsers); 559 return; 560 } 561 562 mNetworkCallback = 563 new ConnectivityManager.NetworkCallback() { 564 @Override 565 public void onAvailable(Network network) { 566 compareAndSetLoadEscrowDataErrorCode( 567 ERROR_NO_NETWORK, ERROR_NONE, retryHandler); 568 569 if (!mLoadEscrowDataWithRetry) { 570 mLoadEscrowDataWithRetry = true; 571 // Only kickoff retry mechanism on first onAvailable call. 572 loadRebootEscrowDataWithRetry( 573 retryHandler, 574 /* attemptNumber = */ 0, 575 users, 576 rebootEscrowUsers); 577 } 578 } 579 580 @Override 581 public void onUnavailable() { 582 Slog.w(TAG, "Failed to connect to network within timeout"); 583 compareAndSetLoadEscrowDataErrorCode( 584 ERROR_NONE, ERROR_NO_NETWORK, retryHandler); 585 onGetRebootEscrowKeyFailed(users, /* attemptCount= */ 0, retryHandler); 586 } 587 588 @Override 589 public void onLost(Network lostNetwork) { 590 // TODO(b/231660348): If network is lost, wait for network to become 591 // available again. 592 Slog.w(TAG, "Network lost, still attempting to load escrow key."); 593 compareAndSetLoadEscrowDataErrorCode( 594 ERROR_NONE, ERROR_NO_NETWORK, retryHandler); 595 } 596 }; 597 598 // Fallback to retrying without waiting for internet on failure. 599 boolean success = mInjector.requestNetworkWithInternet(mNetworkCallback); 600 if (!success) { 601 loadRebootEscrowDataWithRetry( 602 retryHandler, /* attemptNumber = */ 0, users, rebootEscrowUsers); 603 } 604 } 605 loadRebootEscrowDataWithRetry( Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)606 void loadRebootEscrowDataWithRetry( 607 Handler retryHandler, 608 int attemptNumber, 609 List<UserInfo> users, 610 List<UserInfo> rebootEscrowUsers) { 611 // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is 612 // generated before reboot. Note that we will clear the escrow key even if the keystore key 613 // is null. 614 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 615 if (kk == null) { 616 Slog.i(TAG, "Failed to load the key for resume on reboot from key store."); 617 } 618 619 RebootEscrowKey escrowKey; 620 try { 621 escrowKey = getAndClearRebootEscrowKey(kk, retryHandler); 622 } catch (IOException e) { 623 Slog.i(TAG, "Failed to load escrow key, scheduling retry.", e); 624 scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users, 625 rebootEscrowUsers); 626 return; 627 } 628 629 if (escrowKey == null) { 630 if (mLoadEscrowDataErrorCode == ERROR_NONE) { 631 // Specifically check if the RoR provider has changed after reboot. 632 int providerType = mInjector.serverBasedResumeOnReboot() 633 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 634 : RebootEscrowProviderInterface.TYPE_HAL; 635 if (providerType != mStorage.getInt(REBOOT_ESCROW_KEY_PROVIDER, -1, USER_SYSTEM)) { 636 setLoadEscrowDataErrorCode(ERROR_PROVIDER_MISMATCH, retryHandler); 637 } else { 638 setLoadEscrowDataErrorCode(ERROR_LOAD_ESCROW_KEY, retryHandler); 639 } 640 } 641 onGetRebootEscrowKeyFailed(users, attemptNumber + 1, retryHandler); 642 return; 643 } 644 645 mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA); 646 647 boolean allUsersUnlocked = true; 648 for (UserInfo user : rebootEscrowUsers) { 649 allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk); 650 } 651 652 if (!allUsersUnlocked) { 653 compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_UNLOCK_ALL_USERS, retryHandler); 654 } 655 onEscrowRestoreComplete(allUsersUnlocked, attemptNumber + 1, retryHandler); 656 } 657 clearMetricsStorage()658 private void clearMetricsStorage() { 659 mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); 660 mStorage.removeKey(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, USER_SYSTEM); 661 mStorage.removeKey(REBOOT_ESCROW_KEY_VBMETA_DIGEST, USER_SYSTEM); 662 mStorage.removeKey(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, USER_SYSTEM); 663 mStorage.removeKey(REBOOT_ESCROW_KEY_PROVIDER, USER_SYSTEM); 664 } 665 getVbmetaDigestStatusOnRestoreComplete()666 private int getVbmetaDigestStatusOnRestoreComplete() { 667 String currentVbmetaDigest = mInjector.getVbmetaDigest(false); 668 String vbmetaDigestStored = mStorage.getString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, 669 "", USER_SYSTEM); 670 String vbmetaDigestOtherStored = mStorage.getString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 671 "", USER_SYSTEM); 672 673 // The other vbmeta digest is never set, assume no slot switch is attempted. 674 if (vbmetaDigestOtherStored.isEmpty()) { 675 if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 676 return FrameworkStatsLog 677 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 678 } 679 return FrameworkStatsLog 680 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 681 } 682 683 // The other vbmeta digest is set, we expect to boot into the new slot. 684 if (currentVbmetaDigest.equals(vbmetaDigestOtherStored)) { 685 return FrameworkStatsLog 686 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 687 } else if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 688 return FrameworkStatsLog 689 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_FALLBACK_SLOT; 690 } 691 return FrameworkStatsLog 692 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 693 } 694 reportMetricOnRestoreComplete( boolean success, int attemptCount, Handler retryHandler)695 private void reportMetricOnRestoreComplete( 696 boolean success, int attemptCount, Handler retryHandler) { 697 int serviceType = mInjector.serverBasedResumeOnReboot() 698 ? FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__SERVER_BASED 699 : FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__HAL; 700 701 long armedTimestamp = mStorage.getLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, -1, 702 USER_SYSTEM); 703 int escrowDurationInSeconds = -1; 704 long currentTimeStamp = mInjector.getCurrentTimeMillis(); 705 if (armedTimestamp != -1 && currentTimeStamp > armedTimestamp) { 706 escrowDurationInSeconds = (int) (currentTimeStamp - armedTimestamp) / 1000; 707 } 708 709 int vbmetaDigestStatus = getVbmetaDigestStatusOnRestoreComplete(); 710 if (!success) { 711 compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_UNKNOWN, retryHandler); 712 } 713 714 Slog.i( 715 TAG, 716 "Reporting RoR recovery metrics, success: " 717 + success 718 + ", service type: " 719 + serviceType 720 + ", error code: " 721 + mLoadEscrowDataErrorCode); 722 // TODO(179105110) report the duration since boot complete. 723 mInjector.reportMetric( 724 success, 725 mLoadEscrowDataErrorCode, 726 serviceType, 727 attemptCount, 728 escrowDurationInSeconds, 729 vbmetaDigestStatus, 730 -1); 731 732 setLoadEscrowDataErrorCode(ERROR_NONE, retryHandler); 733 } 734 onEscrowRestoreComplete(boolean success, int attemptCount, Handler retryHandler)735 private void onEscrowRestoreComplete(boolean success, int attemptCount, Handler retryHandler) { 736 int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM); 737 738 int bootCountDelta = mInjector.getBootCount() - previousBootCount; 739 if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) { 740 reportMetricOnRestoreComplete(success, attemptCount, retryHandler); 741 } 742 // Clear the old key in keystore. A new key will be generated by new RoR requests. 743 mKeyStoreManager.clearKeyStoreEncryptionKey(); 744 // Clear the saved reboot escrow provider 745 mInjector.clearRebootEscrowProvider(); 746 clearMetricsStorage(); 747 748 if (mNetworkCallback != null) { 749 mInjector.stopRequestingNetwork(mNetworkCallback); 750 } 751 752 if (mWakeLock != null) { 753 mWakeLock.release(); 754 } 755 } 756 getAndClearRebootEscrowKey(SecretKey kk, Handler retryHandler)757 private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk, Handler retryHandler) 758 throws IOException { 759 RebootEscrowProviderInterface rebootEscrowProvider = 760 mInjector.createRebootEscrowProviderIfNeeded(); 761 if (rebootEscrowProvider == null) { 762 Slog.w( 763 TAG, 764 "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); 765 setLoadEscrowDataErrorCode(ERROR_NO_PROVIDER, retryHandler); 766 return null; 767 } 768 769 // Server based RoR always need the decryption key from keystore. 770 if (rebootEscrowProvider.getType() == RebootEscrowProviderInterface.TYPE_SERVER_BASED 771 && kk == null) { 772 setLoadEscrowDataErrorCode(ERROR_KEYSTORE_FAILURE, retryHandler); 773 return null; 774 } 775 776 // The K_s blob maybe encrypted by K_k as well. 777 RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(kk); 778 if (key != null) { 779 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK); 780 } 781 return key; 782 } 783 restoreRebootEscrowForUser(@serIdInt int userId, RebootEscrowKey ks, SecretKey kk)784 private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey ks, 785 SecretKey kk) { 786 if (!mStorage.hasRebootEscrow(userId)) { 787 return false; 788 } 789 790 try { 791 byte[] blob = mStorage.readRebootEscrow(userId); 792 mStorage.removeRebootEscrow(userId); 793 794 RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(ks, blob, kk); 795 796 mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(), 797 escrowData.getSyntheticPassword(), userId); 798 Slog.i(TAG, "Restored reboot escrow data for user " + userId); 799 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId); 800 return true; 801 } catch (IOException e) { 802 Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); 803 return false; 804 } 805 } 806 callToRebootEscrowIfNeeded(@serIdInt int userId, byte spVersion, byte[] syntheticPassword)807 void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion, 808 byte[] syntheticPassword) { 809 if (!mRebootEscrowWanted) { 810 return; 811 } 812 813 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 814 Slog.w(TAG, "Not storing escrow data, RebootEscrowProvider is unavailable"); 815 return; 816 } 817 818 RebootEscrowKey escrowKey = generateEscrowKeyIfNeeded(); 819 if (escrowKey == null) { 820 Slog.e(TAG, "Could not generate escrow key"); 821 return; 822 } 823 824 SecretKey kk = mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded(); 825 if (kk == null) { 826 Slog.e(TAG, "Failed to generate encryption key from keystore."); 827 return; 828 } 829 830 final RebootEscrowData escrowData; 831 try { 832 escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion, 833 syntheticPassword, kk); 834 } catch (IOException e) { 835 setRebootEscrowReady(false); 836 Slog.w(TAG, "Could not escrow reboot data", e); 837 return; 838 } 839 840 mStorage.writeRebootEscrow(userId, escrowData.getBlob()); 841 mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId); 842 843 setRebootEscrowReady(true); 844 } 845 generateEscrowKeyIfNeeded()846 private RebootEscrowKey generateEscrowKeyIfNeeded() { 847 synchronized (mKeyGenerationLock) { 848 if (mPendingRebootEscrowKey != null) { 849 return mPendingRebootEscrowKey; 850 } 851 852 RebootEscrowKey key; 853 try { 854 key = RebootEscrowKey.generate(); 855 } catch (IOException e) { 856 Slog.w(TAG, "Could not generate reboot escrow key"); 857 return null; 858 } 859 860 mPendingRebootEscrowKey = key; 861 return key; 862 } 863 } 864 clearRebootEscrowIfNeeded()865 private void clearRebootEscrowIfNeeded() { 866 mRebootEscrowWanted = false; 867 setRebootEscrowReady(false); 868 869 // We want to clear the internal data inside the provider, so always try to create the 870 // provider. 871 RebootEscrowProviderInterface rebootEscrowProvider = 872 mInjector.createRebootEscrowProviderIfNeeded(); 873 if (rebootEscrowProvider == null) { 874 Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request"); 875 } else { 876 rebootEscrowProvider.clearRebootEscrowKey(); 877 } 878 879 mInjector.clearRebootEscrowProvider(); 880 clearMetricsStorage(); 881 882 List<UserInfo> users = mUserManager.getUsers(); 883 for (UserInfo user : users) { 884 mStorage.removeRebootEscrow(user.id); 885 } 886 887 mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); 888 } 889 armRebootEscrowIfNeeded()890 @ArmRebootEscrowErrorCode int armRebootEscrowIfNeeded() { 891 if (!mRebootEscrowReady) { 892 return ARM_REBOOT_ERROR_ESCROW_NOT_READY; 893 } 894 895 RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); 896 if (rebootEscrowProvider == null) { 897 Slog.w(TAG, "Not storing escrow key, RebootEscrowProvider is unavailable"); 898 clearRebootEscrowIfNeeded(); 899 return ARM_REBOOT_ERROR_NO_PROVIDER; 900 } 901 902 int expectedProviderType = mInjector.serverBasedResumeOnReboot() 903 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 904 : RebootEscrowProviderInterface.TYPE_HAL; 905 int actualProviderType = rebootEscrowProvider.getType(); 906 if (expectedProviderType != actualProviderType) { 907 Slog.w(TAG, "Expect reboot escrow provider " + expectedProviderType 908 + ", but the RoR is prepared with " + actualProviderType 909 + ". Please prepare the RoR again."); 910 clearRebootEscrowIfNeeded(); 911 return ARM_REBOOT_ERROR_PROVIDER_MISMATCH; 912 } 913 914 RebootEscrowKey escrowKey; 915 synchronized (mKeyGenerationLock) { 916 escrowKey = mPendingRebootEscrowKey; 917 } 918 919 if (escrowKey == null) { 920 Slog.e(TAG, "Escrow key is null, but escrow was marked as ready"); 921 clearRebootEscrowIfNeeded(); 922 return ARM_REBOOT_ERROR_NO_ESCROW_KEY; 923 } 924 925 // We will use the same key from keystore to encrypt the escrow key and escrow data blob. 926 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 927 if (kk == null) { 928 Slog.e(TAG, "Failed to get encryption key from keystore."); 929 clearRebootEscrowIfNeeded(); 930 return ARM_REBOOT_ERROR_KEYSTORE_FAILURE; 931 } 932 933 // TODO(b/183140900) design detailed errors for store escrow key errors. 934 // We don't clear rebootEscrow here, because some errors may be recoverable, e.g. network 935 // unavailable for server based provider. 936 boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); 937 if (!armedRebootEscrow) { 938 return ARM_REBOOT_ERROR_STORE_ESCROW_KEY; 939 } 940 941 mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); 942 mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, mInjector.getCurrentTimeMillis(), 943 USER_SYSTEM); 944 // Store the vbmeta digest of both slots. 945 mStorage.setString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, mInjector.getVbmetaDigest(false), 946 USER_SYSTEM); 947 mStorage.setString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 948 mInjector.getVbmetaDigest(true), USER_SYSTEM); 949 mStorage.setInt(REBOOT_ESCROW_KEY_PROVIDER, actualProviderType, USER_SYSTEM); 950 mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); 951 952 return ARM_REBOOT_ERROR_NONE; 953 } 954 setRebootEscrowReady(boolean ready)955 private void setRebootEscrowReady(boolean ready) { 956 if (mRebootEscrowReady != ready) { 957 mHandler.post(() -> mRebootEscrowListener.onPreparedForReboot(ready)); 958 } 959 mRebootEscrowReady = ready; 960 } 961 prepareRebootEscrow()962 boolean prepareRebootEscrow() { 963 clearRebootEscrowIfNeeded(); 964 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 965 Slog.w(TAG, "No reboot escrow provider, skipping resume on reboot preparation."); 966 return false; 967 } 968 969 mRebootEscrowWanted = true; 970 mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF); 971 return true; 972 } 973 clearRebootEscrow()974 boolean clearRebootEscrow() { 975 clearRebootEscrowIfNeeded(); 976 return true; 977 } 978 setRebootEscrowListener(RebootEscrowListener listener)979 void setRebootEscrowListener(RebootEscrowListener listener) { 980 mRebootEscrowListener = listener; 981 } 982 983 @VisibleForTesting 984 public static class RebootEscrowEvent { 985 static final int FOUND_ESCROW_DATA = 1; 986 static final int SET_ARMED_STATUS = 2; 987 static final int CLEARED_LSKF_REQUEST = 3; 988 static final int RETRIEVED_STORED_KEK = 4; 989 static final int REQUESTED_LSKF = 5; 990 static final int STORED_LSKF_FOR_USER = 6; 991 static final int RETRIEVED_LSKF_FOR_USER = 7; 992 993 final int mEventId; 994 final Integer mUserId; 995 final long mWallTime; 996 final long mTimestamp; 997 RebootEscrowEvent(int eventId)998 RebootEscrowEvent(int eventId) { 999 this(eventId, null); 1000 } 1001 RebootEscrowEvent(int eventId, Integer userId)1002 RebootEscrowEvent(int eventId, Integer userId) { 1003 mEventId = eventId; 1004 mUserId = userId; 1005 mTimestamp = SystemClock.uptimeMillis(); 1006 mWallTime = System.currentTimeMillis(); 1007 } 1008 getEventDescription()1009 String getEventDescription() { 1010 switch (mEventId) { 1011 case FOUND_ESCROW_DATA: 1012 return "Found escrow data"; 1013 case SET_ARMED_STATUS: 1014 return "Set armed status"; 1015 case CLEARED_LSKF_REQUEST: 1016 return "Cleared request for LSKF"; 1017 case RETRIEVED_STORED_KEK: 1018 return "Retrieved stored KEK"; 1019 case REQUESTED_LSKF: 1020 return "Requested LSKF"; 1021 case STORED_LSKF_FOR_USER: 1022 return "Stored LSKF for user"; 1023 case RETRIEVED_LSKF_FOR_USER: 1024 return "Retrieved LSKF for user"; 1025 default: 1026 return "Unknown event ID " + mEventId; 1027 } 1028 } 1029 } 1030 1031 @VisibleForTesting 1032 public static class RebootEscrowEventLog { 1033 private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16]; 1034 private int mNextIndex = 0; 1035 addEntry(int eventId)1036 void addEntry(int eventId) { 1037 addEntryInternal(new RebootEscrowEvent(eventId)); 1038 } 1039 addEntry(int eventId, int userId)1040 void addEntry(int eventId, int userId) { 1041 addEntryInternal(new RebootEscrowEvent(eventId, userId)); 1042 } 1043 addEntryInternal(RebootEscrowEvent event)1044 private void addEntryInternal(RebootEscrowEvent event) { 1045 final int index = mNextIndex; 1046 mEntries[index] = event; 1047 mNextIndex = (mNextIndex + 1) % mEntries.length; 1048 } 1049 dump(@onNull IndentingPrintWriter pw)1050 void dump(@NonNull IndentingPrintWriter pw) { 1051 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); 1052 1053 for (int i = 0; i < mEntries.length; ++i) { 1054 RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length]; 1055 if (event == null) { 1056 continue; 1057 } 1058 1059 pw.print("Event #"); 1060 pw.println(i); 1061 1062 pw.println(" time=" + sdf.format(new Date(event.mWallTime)) 1063 + " (timestamp=" + event.mTimestamp + ")"); 1064 1065 pw.print(" event="); 1066 pw.println(event.getEventDescription()); 1067 1068 if (event.mUserId != null) { 1069 pw.print(" user="); 1070 pw.println(event.mUserId); 1071 } 1072 } 1073 } 1074 } 1075 dump(@onNull IndentingPrintWriter pw)1076 void dump(@NonNull IndentingPrintWriter pw) { 1077 pw.print("mRebootEscrowWanted="); 1078 pw.println(mRebootEscrowWanted); 1079 1080 pw.print("mRebootEscrowReady="); 1081 pw.println(mRebootEscrowReady); 1082 1083 pw.print("mRebootEscrowListener="); 1084 pw.println(mRebootEscrowListener); 1085 1086 pw.print("mLoadEscrowDataErrorCode="); 1087 pw.println(mLoadEscrowDataErrorCode); 1088 1089 boolean keySet; 1090 synchronized (mKeyGenerationLock) { 1091 keySet = mPendingRebootEscrowKey != null; 1092 } 1093 1094 pw.print("mPendingRebootEscrowKey is "); 1095 pw.println(keySet ? "set" : "not set"); 1096 1097 RebootEscrowProviderInterface provider = mInjector.getRebootEscrowProvider(); 1098 String providerType = provider == null ? "null" : String.valueOf(provider.getType()); 1099 pw.print("RebootEscrowProvider type is " + providerType); 1100 1101 pw.println(); 1102 pw.println("Event log:"); 1103 pw.increaseIndent(); 1104 mEventLog.dump(pw); 1105 pw.println(); 1106 pw.decreaseIndent(); 1107 } 1108 } 1109