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.os.Handler; 40 import android.os.PowerManager; 41 import android.os.SystemClock; 42 import android.os.SystemProperties; 43 import android.os.UserManager; 44 import android.provider.DeviceConfig; 45 import android.provider.Settings; 46 import android.util.Slog; 47 48 import com.android.internal.annotations.GuardedBy; 49 import com.android.internal.annotations.VisibleForTesting; 50 import com.android.internal.util.FrameworkStatsLog; 51 import com.android.internal.util.IndentingPrintWriter; 52 import com.android.internal.widget.RebootEscrowListener; 53 54 import java.io.IOException; 55 import java.lang.annotation.Retention; 56 import java.lang.annotation.RetentionPolicy; 57 import java.text.SimpleDateFormat; 58 import java.util.ArrayList; 59 import java.util.Date; 60 import java.util.List; 61 import java.util.Locale; 62 import java.util.Objects; 63 64 import javax.crypto.SecretKey; 65 66 /** 67 * This class aims to persists the synthetic password(SP) across reboot in a secure way. In 68 * particular, it manages the encryption of the sp before reboot, and decryption of the sp after 69 * reboot. Here are the meaning of some terms. 70 * SP: synthetic password 71 * K_s: The RebootEscrowKey, i.e. AES-GCM key stored in memory 72 * K_k: AES-GCM key in android keystore 73 * RebootEscrowData: The synthetic password and its encrypted blob. We encrypt SP with K_s first, 74 * then with K_k, i.e. E(K_k, E(K_s, SP)) 75 */ 76 class RebootEscrowManager { 77 private static final String TAG = "RebootEscrowManager"; 78 79 /** 80 * Used in the database storage to indicate the boot count at which the reboot escrow was 81 * previously armed. 82 */ 83 @VisibleForTesting 84 public static final String REBOOT_ESCROW_ARMED_KEY = "reboot_escrow_armed_count"; 85 86 static final String REBOOT_ESCROW_KEY_ARMED_TIMESTAMP = "reboot_escrow_key_stored_timestamp"; 87 static final String REBOOT_ESCROW_KEY_PROVIDER = "reboot_escrow_key_provider"; 88 89 /** 90 * The verified boot 2.0 vbmeta digest of the current slot, the property value is always 91 * available after boot. 92 */ 93 static final String VBMETA_DIGEST_PROP_NAME = "ro.boot.vbmeta.digest"; 94 /** 95 * The system prop contains vbmeta digest of the inactive slot. The build property is set after 96 * an OTA update. RebootEscrowManager will store it in disk before the OTA reboot, so the value 97 * is available for vbmeta digest verification after the device reboots. 98 */ 99 static final String OTHER_VBMETA_DIGEST_PROP_NAME = "ota.other.vbmeta_digest"; 100 static final String REBOOT_ESCROW_KEY_VBMETA_DIGEST = "reboot_escrow_key_vbmeta_digest"; 101 static final String REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST = 102 "reboot_escrow_key_other_vbmeta_digest"; 103 104 /** 105 * Number of boots until we consider the escrow data to be stale for the purposes of metrics. 106 * <p> 107 * If the delta between the current boot number and the boot number stored when the mechanism 108 * was armed is under this number and the escrow mechanism fails, we report it as a failure of 109 * the mechanism. 110 * <p> 111 * If the delta over this number and escrow fails, we will not report the metric as failed 112 * since there most likely was some other issue if the device rebooted several times before 113 * getting to the escrow restore code. 114 */ 115 private static final int BOOT_COUNT_TOLERANCE = 5; 116 117 /** 118 * The default retry specs for loading reboot escrow data. We will attempt to retry loading 119 * escrow data on temporarily errors, e.g. unavailable network. 120 */ 121 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3; 122 private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30; 123 // 3 minutes. It's enough for the default 3 retries with 30 seconds interval 124 private static final int DEFAULT_WAKE_LOCK_TIMEOUT_MILLIS = 180_000; 125 126 @IntDef(prefix = {"ERROR_"}, value = { 127 ERROR_NONE, 128 ERROR_UNKNOWN, 129 ERROR_NO_PROVIDER, 130 ERROR_LOAD_ESCROW_KEY, 131 ERROR_RETRY_COUNT_EXHAUSTED, 132 ERROR_UNLOCK_ALL_USERS, 133 ERROR_PROVIDER_MISMATCH, 134 ERROR_KEYSTORE_FAILURE, 135 ERROR_NO_NETWORK, 136 }) 137 @Retention(RetentionPolicy.SOURCE) 138 @interface RebootEscrowErrorCode { 139 } 140 141 static final int ERROR_NONE = 0; 142 static final int ERROR_UNKNOWN = 1; 143 static final int ERROR_NO_PROVIDER = 2; 144 static final int ERROR_LOAD_ESCROW_KEY = 3; 145 static final int ERROR_RETRY_COUNT_EXHAUSTED = 4; 146 static final int ERROR_UNLOCK_ALL_USERS = 5; 147 static final int ERROR_PROVIDER_MISMATCH = 6; 148 static final int ERROR_KEYSTORE_FAILURE = 7; 149 static final int ERROR_NO_NETWORK = 8; 150 151 private @RebootEscrowErrorCode int mLoadEscrowDataErrorCode = ERROR_NONE; 152 153 /** 154 * Logs events for later debugging in bugreports. 155 */ 156 private final RebootEscrowEventLog mEventLog; 157 158 /** 159 * Used to track when the reboot escrow is wanted. Should stay true once escrow is requested 160 * unless clearRebootEscrow is called. This will allow all the active users to be unlocked 161 * after reboot. 162 */ 163 private boolean mRebootEscrowWanted; 164 165 /** Used to track when reboot escrow is ready. */ 166 private boolean mRebootEscrowReady; 167 168 /** Notified when mRebootEscrowReady changes. */ 169 private RebootEscrowListener mRebootEscrowListener; 170 171 /** 172 * Hold this lock when checking or generating the reboot escrow key. 173 */ 174 private final Object mKeyGenerationLock = new Object(); 175 176 /** 177 * Stores the reboot escrow data between when it's supplied and when 178 * {@link #armRebootEscrowIfNeeded()} is called. 179 */ 180 @GuardedBy("mKeyGenerationLock") 181 private RebootEscrowKey mPendingRebootEscrowKey; 182 183 private final UserManager mUserManager; 184 185 private final Injector mInjector; 186 187 private final LockSettingsStorage mStorage; 188 189 private final Callbacks mCallbacks; 190 191 private final RebootEscrowKeyStoreManager mKeyStoreManager; 192 193 PowerManager.WakeLock mWakeLock; 194 195 196 interface Callbacks { isUserSecure(int userId)197 boolean isUserSecure(int userId); 198 onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId)199 void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId); 200 } 201 202 static class Injector { 203 protected Context mContext; 204 private final RebootEscrowKeyStoreManager mKeyStoreManager; 205 private final LockSettingsStorage mStorage; 206 private RebootEscrowProviderInterface mRebootEscrowProvider; 207 Injector(Context context, LockSettingsStorage storage)208 Injector(Context context, LockSettingsStorage storage) { 209 mContext = context; 210 mStorage = storage; 211 mKeyStoreManager = new RebootEscrowKeyStoreManager(); 212 } 213 createRebootEscrowProvider()214 private RebootEscrowProviderInterface createRebootEscrowProvider() { 215 RebootEscrowProviderInterface rebootEscrowProvider; 216 if (serverBasedResumeOnReboot()) { 217 Slog.i(TAG, "Using server based resume on reboot"); 218 rebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(mContext, mStorage); 219 } else { 220 Slog.i(TAG, "Using HAL based resume on reboot"); 221 rebootEscrowProvider = new RebootEscrowProviderHalImpl(); 222 } 223 224 if (rebootEscrowProvider.hasRebootEscrowSupport()) { 225 return rebootEscrowProvider; 226 } 227 return null; 228 } 229 post(Handler handler, Runnable runnable)230 void post(Handler handler, Runnable runnable) { 231 handler.post(runnable); 232 } 233 postDelayed(Handler handler, Runnable runnable, long delayMillis)234 void postDelayed(Handler handler, Runnable runnable, long delayMillis) { 235 handler.postDelayed(runnable, delayMillis); 236 } 237 serverBasedResumeOnReboot()238 public boolean serverBasedResumeOnReboot() { 239 // Always use the server based RoR if the HAL isn't installed on device. 240 if (!mContext.getPackageManager().hasSystemFeature( 241 PackageManager.FEATURE_REBOOT_ESCROW)) { 242 return true; 243 } 244 245 return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, 246 "server_based_ror_enabled", false); 247 } 248 isNetworkConnected()249 public boolean isNetworkConnected() { 250 final ConnectivityManager connectivityManager = 251 mContext.getSystemService(ConnectivityManager.class); 252 if (connectivityManager == null) { 253 return false; 254 } 255 256 Network activeNetwork = connectivityManager.getActiveNetwork(); 257 NetworkCapabilities networkCapabilities = 258 connectivityManager.getNetworkCapabilities(activeNetwork); 259 return networkCapabilities != null 260 && networkCapabilities.hasCapability( 261 NetworkCapabilities.NET_CAPABILITY_INTERNET) 262 && networkCapabilities.hasCapability( 263 NetworkCapabilities.NET_CAPABILITY_VALIDATED); 264 } 265 getContext()266 public Context getContext() { 267 return mContext; 268 } 269 getUserManager()270 public UserManager getUserManager() { 271 return (UserManager) mContext.getSystemService(Context.USER_SERVICE); 272 } 273 getKeyStoreManager()274 public RebootEscrowKeyStoreManager getKeyStoreManager() { 275 return mKeyStoreManager; 276 } 277 createRebootEscrowProviderIfNeeded()278 public RebootEscrowProviderInterface createRebootEscrowProviderIfNeeded() { 279 // Initialize for the provider lazily. Because the device_config and service 280 // implementation apps may change when system server is running. 281 if (mRebootEscrowProvider == null) { 282 mRebootEscrowProvider = createRebootEscrowProvider(); 283 } 284 285 return mRebootEscrowProvider; 286 } 287 getWakeLock()288 PowerManager.WakeLock getWakeLock() { 289 final PowerManager pm = mContext.getSystemService(PowerManager.class); 290 return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RebootEscrowManager"); 291 } 292 getRebootEscrowProvider()293 public RebootEscrowProviderInterface getRebootEscrowProvider() { 294 return mRebootEscrowProvider; 295 } 296 clearRebootEscrowProvider()297 public void clearRebootEscrowProvider() { 298 mRebootEscrowProvider = null; 299 } 300 getBootCount()301 public int getBootCount() { 302 return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 303 0); 304 } 305 getCurrentTimeMillis()306 public long getCurrentTimeMillis() { 307 return System.currentTimeMillis(); 308 } 309 getLoadEscrowDataRetryLimit()310 public int getLoadEscrowDataRetryLimit() { 311 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 312 "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT); 313 } 314 getLoadEscrowDataRetryIntervalSeconds()315 public int getLoadEscrowDataRetryIntervalSeconds() { 316 return DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA, 317 "load_escrow_data_retry_interval_seconds", 318 DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS); 319 } 320 reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootCompleteInSeconds)321 public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, 322 int escrowDurationInSeconds, int vbmetaDigestStatus, 323 int durationSinceBootCompleteInSeconds) { 324 FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success, 325 errorCode, serviceType, attemptCount, escrowDurationInSeconds, 326 vbmetaDigestStatus, durationSinceBootCompleteInSeconds); 327 } 328 getEventLog()329 public RebootEscrowEventLog getEventLog() { 330 return new RebootEscrowEventLog(); 331 } 332 getVbmetaDigest(boolean other)333 public String getVbmetaDigest(boolean other) { 334 return other ? SystemProperties.get(OTHER_VBMETA_DIGEST_PROP_NAME) 335 : SystemProperties.get(VBMETA_DIGEST_PROP_NAME); 336 } 337 } 338 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage)339 RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) { 340 this(new Injector(context, storage), callbacks, storage); 341 } 342 343 @VisibleForTesting RebootEscrowManager(Injector injector, Callbacks callbacks, LockSettingsStorage storage)344 RebootEscrowManager(Injector injector, Callbacks callbacks, 345 LockSettingsStorage storage) { 346 mInjector = injector; 347 mCallbacks = callbacks; 348 mStorage = storage; 349 mUserManager = injector.getUserManager(); 350 mEventLog = injector.getEventLog(); 351 mKeyStoreManager = injector.getKeyStoreManager(); 352 } 353 onGetRebootEscrowKeyFailed(List<UserInfo> users, int attemptCount)354 private void onGetRebootEscrowKeyFailed(List<UserInfo> users, int attemptCount) { 355 Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage."); 356 for (UserInfo user : users) { 357 mStorage.removeRebootEscrow(user.id); 358 } 359 360 onEscrowRestoreComplete(false, attemptCount); 361 } 362 loadRebootEscrowDataIfAvailable(Handler retryHandler)363 void loadRebootEscrowDataIfAvailable(Handler retryHandler) { 364 List<UserInfo> users = mUserManager.getUsers(); 365 List<UserInfo> rebootEscrowUsers = new ArrayList<>(); 366 for (UserInfo user : users) { 367 if (mCallbacks.isUserSecure(user.id) && mStorage.hasRebootEscrow(user.id)) { 368 rebootEscrowUsers.add(user); 369 } 370 } 371 372 if (rebootEscrowUsers.isEmpty()) { 373 Slog.i(TAG, "No reboot escrow data found for users," 374 + " skipping loading escrow data"); 375 clearMetricsStorage(); 376 return; 377 } 378 379 // Acquire the wake lock to make sure our scheduled task will run. 380 mWakeLock = mInjector.getWakeLock(); 381 if (mWakeLock != null) { 382 mWakeLock.setReferenceCounted(false); 383 mWakeLock.acquire(DEFAULT_WAKE_LOCK_TIMEOUT_MILLIS); 384 } 385 386 mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry( 387 retryHandler, 0, users, rebootEscrowUsers)); 388 } 389 scheduleLoadRebootEscrowDataOrFail(Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)390 void scheduleLoadRebootEscrowDataOrFail(Handler retryHandler, int attemptNumber, 391 List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { 392 Objects.requireNonNull(retryHandler); 393 394 final int retryLimit = mInjector.getLoadEscrowDataRetryLimit(); 395 final int retryIntervalInSeconds = mInjector.getLoadEscrowDataRetryIntervalSeconds(); 396 397 if (attemptNumber < retryLimit) { 398 Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber); 399 mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry( 400 retryHandler, attemptNumber, users, rebootEscrowUsers), 401 retryIntervalInSeconds * 1000); 402 return; 403 } 404 405 Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); 406 if (mInjector.serverBasedResumeOnReboot() && !mInjector.isNetworkConnected()) { 407 mLoadEscrowDataErrorCode = ERROR_NO_NETWORK; 408 } else { 409 mLoadEscrowDataErrorCode = ERROR_RETRY_COUNT_EXHAUSTED; 410 } 411 onGetRebootEscrowKeyFailed(users, attemptNumber); 412 } 413 loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber, List<UserInfo> users, List<UserInfo> rebootEscrowUsers)414 void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber, 415 List<UserInfo> users, List<UserInfo> rebootEscrowUsers) { 416 // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is 417 // generated before reboot. Note that we will clear the escrow key even if the keystore key 418 // is null. 419 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 420 if (kk == null) { 421 Slog.i(TAG, "Failed to load the key for resume on reboot from key store."); 422 } 423 424 RebootEscrowKey escrowKey; 425 try { 426 escrowKey = getAndClearRebootEscrowKey(kk); 427 } catch (IOException e) { 428 Slog.i(TAG, "Failed to load escrow key, scheduling retry.", e); 429 scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users, 430 rebootEscrowUsers); 431 return; 432 } 433 434 if (escrowKey == null) { 435 if (mLoadEscrowDataErrorCode == ERROR_NONE) { 436 // Specifically check if the RoR provider has changed after reboot. 437 int providerType = mInjector.serverBasedResumeOnReboot() 438 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 439 : RebootEscrowProviderInterface.TYPE_HAL; 440 if (providerType != mStorage.getInt(REBOOT_ESCROW_KEY_PROVIDER, -1, USER_SYSTEM)) { 441 mLoadEscrowDataErrorCode = ERROR_PROVIDER_MISMATCH; 442 } else { 443 mLoadEscrowDataErrorCode = ERROR_LOAD_ESCROW_KEY; 444 } 445 } 446 onGetRebootEscrowKeyFailed(users, attemptNumber + 1); 447 return; 448 } 449 450 mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA); 451 452 boolean allUsersUnlocked = true; 453 for (UserInfo user : rebootEscrowUsers) { 454 allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk); 455 } 456 457 if (!allUsersUnlocked && mLoadEscrowDataErrorCode == ERROR_NONE) { 458 mLoadEscrowDataErrorCode = ERROR_UNLOCK_ALL_USERS; 459 } 460 onEscrowRestoreComplete(allUsersUnlocked, attemptNumber + 1); 461 } 462 clearMetricsStorage()463 private void clearMetricsStorage() { 464 mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); 465 mStorage.removeKey(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, USER_SYSTEM); 466 mStorage.removeKey(REBOOT_ESCROW_KEY_VBMETA_DIGEST, USER_SYSTEM); 467 mStorage.removeKey(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, USER_SYSTEM); 468 mStorage.removeKey(REBOOT_ESCROW_KEY_PROVIDER, USER_SYSTEM); 469 } 470 getVbmetaDigestStatusOnRestoreComplete()471 private int getVbmetaDigestStatusOnRestoreComplete() { 472 String currentVbmetaDigest = mInjector.getVbmetaDigest(false); 473 String vbmetaDigestStored = mStorage.getString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, 474 "", USER_SYSTEM); 475 String vbmetaDigestOtherStored = mStorage.getString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 476 "", USER_SYSTEM); 477 478 // The other vbmeta digest is never set, assume no slot switch is attempted. 479 if (vbmetaDigestOtherStored.isEmpty()) { 480 if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 481 return FrameworkStatsLog 482 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 483 } 484 return FrameworkStatsLog 485 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 486 } 487 488 // The other vbmeta digest is set, we expect to boot into the new slot. 489 if (currentVbmetaDigest.equals(vbmetaDigestOtherStored)) { 490 return FrameworkStatsLog 491 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_EXPECTED_SLOT; 492 } else if (currentVbmetaDigest.equals(vbmetaDigestStored)) { 493 return FrameworkStatsLog 494 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MATCH_FALLBACK_SLOT; 495 } 496 return FrameworkStatsLog 497 .REBOOT_ESCROW_RECOVERY_REPORTED__VBMETA_DIGEST_STATUS__MISMATCH; 498 } 499 reportMetricOnRestoreComplete(boolean success, int attemptCount)500 private void reportMetricOnRestoreComplete(boolean success, int attemptCount) { 501 int serviceType = mInjector.serverBasedResumeOnReboot() 502 ? FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__SERVER_BASED 503 : FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED__TYPE__HAL; 504 505 long armedTimestamp = mStorage.getLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, -1, 506 USER_SYSTEM); 507 int escrowDurationInSeconds = -1; 508 long currentTimeStamp = mInjector.getCurrentTimeMillis(); 509 if (armedTimestamp != -1 && currentTimeStamp > armedTimestamp) { 510 escrowDurationInSeconds = (int) (currentTimeStamp - armedTimestamp) / 1000; 511 } 512 513 int vbmetaDigestStatus = getVbmetaDigestStatusOnRestoreComplete(); 514 if (!success && mLoadEscrowDataErrorCode == ERROR_NONE) { 515 mLoadEscrowDataErrorCode = ERROR_UNKNOWN; 516 } 517 518 Slog.i(TAG, "Reporting RoR recovery metrics, success: " + success + ", service type: " 519 + serviceType + ", error code: " + mLoadEscrowDataErrorCode); 520 // TODO(179105110) report the duration since boot complete. 521 mInjector.reportMetric(success, mLoadEscrowDataErrorCode, serviceType, attemptCount, 522 escrowDurationInSeconds, vbmetaDigestStatus, -1); 523 524 mLoadEscrowDataErrorCode = ERROR_NONE; 525 } 526 onEscrowRestoreComplete(boolean success, int attemptCount)527 private void onEscrowRestoreComplete(boolean success, int attemptCount) { 528 int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM); 529 530 int bootCountDelta = mInjector.getBootCount() - previousBootCount; 531 if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) { 532 reportMetricOnRestoreComplete(success, attemptCount); 533 } 534 535 // Clear the old key in keystore. A new key will be generated by new RoR requests. 536 mKeyStoreManager.clearKeyStoreEncryptionKey(); 537 // Clear the saved reboot escrow provider 538 mInjector.clearRebootEscrowProvider(); 539 clearMetricsStorage(); 540 541 if (mWakeLock != null) { 542 mWakeLock.release(); 543 } 544 } 545 getAndClearRebootEscrowKey(SecretKey kk)546 private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException { 547 RebootEscrowProviderInterface rebootEscrowProvider = 548 mInjector.createRebootEscrowProviderIfNeeded(); 549 if (rebootEscrowProvider == null) { 550 Slog.w(TAG, 551 "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); 552 mLoadEscrowDataErrorCode = ERROR_NO_PROVIDER; 553 return null; 554 } 555 556 // Server based RoR always need the decryption key from keystore. 557 if (rebootEscrowProvider.getType() == RebootEscrowProviderInterface.TYPE_SERVER_BASED 558 && kk == null) { 559 mLoadEscrowDataErrorCode = ERROR_KEYSTORE_FAILURE; 560 return null; 561 } 562 563 // The K_s blob maybe encrypted by K_k as well. 564 RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(kk); 565 if (key != null) { 566 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK); 567 } 568 return key; 569 } 570 restoreRebootEscrowForUser(@serIdInt int userId, RebootEscrowKey ks, SecretKey kk)571 private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey ks, 572 SecretKey kk) { 573 if (!mStorage.hasRebootEscrow(userId)) { 574 return false; 575 } 576 577 try { 578 byte[] blob = mStorage.readRebootEscrow(userId); 579 mStorage.removeRebootEscrow(userId); 580 581 RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(ks, blob, kk); 582 583 mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(), 584 escrowData.getSyntheticPassword(), userId); 585 Slog.i(TAG, "Restored reboot escrow data for user " + userId); 586 mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId); 587 return true; 588 } catch (IOException e) { 589 Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); 590 return false; 591 } 592 } 593 callToRebootEscrowIfNeeded(@serIdInt int userId, byte spVersion, byte[] syntheticPassword)594 void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion, 595 byte[] syntheticPassword) { 596 if (!mRebootEscrowWanted) { 597 return; 598 } 599 600 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 601 Slog.w(TAG, "Not storing escrow data, RebootEscrowProvider is unavailable"); 602 return; 603 } 604 605 RebootEscrowKey escrowKey = generateEscrowKeyIfNeeded(); 606 if (escrowKey == null) { 607 Slog.e(TAG, "Could not generate escrow key"); 608 return; 609 } 610 611 SecretKey kk = mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded(); 612 if (kk == null) { 613 Slog.e(TAG, "Failed to generate encryption key from keystore."); 614 return; 615 } 616 617 final RebootEscrowData escrowData; 618 try { 619 escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion, 620 syntheticPassword, kk); 621 } catch (IOException e) { 622 setRebootEscrowReady(false); 623 Slog.w(TAG, "Could not escrow reboot data", e); 624 return; 625 } 626 627 mStorage.writeRebootEscrow(userId, escrowData.getBlob()); 628 mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId); 629 630 setRebootEscrowReady(true); 631 } 632 generateEscrowKeyIfNeeded()633 private RebootEscrowKey generateEscrowKeyIfNeeded() { 634 synchronized (mKeyGenerationLock) { 635 if (mPendingRebootEscrowKey != null) { 636 return mPendingRebootEscrowKey; 637 } 638 639 RebootEscrowKey key; 640 try { 641 key = RebootEscrowKey.generate(); 642 } catch (IOException e) { 643 Slog.w(TAG, "Could not generate reboot escrow key"); 644 return null; 645 } 646 647 mPendingRebootEscrowKey = key; 648 return key; 649 } 650 } 651 clearRebootEscrowIfNeeded()652 private void clearRebootEscrowIfNeeded() { 653 mRebootEscrowWanted = false; 654 setRebootEscrowReady(false); 655 656 // We want to clear the internal data inside the provider, so always try to create the 657 // provider. 658 RebootEscrowProviderInterface rebootEscrowProvider = 659 mInjector.createRebootEscrowProviderIfNeeded(); 660 if (rebootEscrowProvider == null) { 661 Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request"); 662 } else { 663 rebootEscrowProvider.clearRebootEscrowKey(); 664 } 665 666 mInjector.clearRebootEscrowProvider(); 667 clearMetricsStorage(); 668 669 List<UserInfo> users = mUserManager.getUsers(); 670 for (UserInfo user : users) { 671 mStorage.removeRebootEscrow(user.id); 672 } 673 674 mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); 675 } 676 armRebootEscrowIfNeeded()677 @ArmRebootEscrowErrorCode int armRebootEscrowIfNeeded() { 678 if (!mRebootEscrowReady) { 679 return ARM_REBOOT_ERROR_ESCROW_NOT_READY; 680 } 681 682 RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); 683 if (rebootEscrowProvider == null) { 684 Slog.w(TAG, "Not storing escrow key, RebootEscrowProvider is unavailable"); 685 clearRebootEscrowIfNeeded(); 686 return ARM_REBOOT_ERROR_NO_PROVIDER; 687 } 688 689 int expectedProviderType = mInjector.serverBasedResumeOnReboot() 690 ? RebootEscrowProviderInterface.TYPE_SERVER_BASED 691 : RebootEscrowProviderInterface.TYPE_HAL; 692 int actualProviderType = rebootEscrowProvider.getType(); 693 if (expectedProviderType != actualProviderType) { 694 Slog.w(TAG, "Expect reboot escrow provider " + expectedProviderType 695 + ", but the RoR is prepared with " + actualProviderType 696 + ". Please prepare the RoR again."); 697 clearRebootEscrowIfNeeded(); 698 return ARM_REBOOT_ERROR_PROVIDER_MISMATCH; 699 } 700 701 RebootEscrowKey escrowKey; 702 synchronized (mKeyGenerationLock) { 703 escrowKey = mPendingRebootEscrowKey; 704 } 705 706 if (escrowKey == null) { 707 Slog.e(TAG, "Escrow key is null, but escrow was marked as ready"); 708 clearRebootEscrowIfNeeded(); 709 return ARM_REBOOT_ERROR_NO_ESCROW_KEY; 710 } 711 712 // We will use the same key from keystore to encrypt the escrow key and escrow data blob. 713 SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); 714 if (kk == null) { 715 Slog.e(TAG, "Failed to get encryption key from keystore."); 716 clearRebootEscrowIfNeeded(); 717 return ARM_REBOOT_ERROR_KEYSTORE_FAILURE; 718 } 719 720 // TODO(b/183140900) design detailed errors for store escrow key errors. 721 // We don't clear rebootEscrow here, because some errors may be recoverable, e.g. network 722 // unavailable for server based provider. 723 boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); 724 if (!armedRebootEscrow) { 725 return ARM_REBOOT_ERROR_STORE_ESCROW_KEY; 726 } 727 728 mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); 729 mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, mInjector.getCurrentTimeMillis(), 730 USER_SYSTEM); 731 // Store the vbmeta digest of both slots. 732 mStorage.setString(REBOOT_ESCROW_KEY_VBMETA_DIGEST, mInjector.getVbmetaDigest(false), 733 USER_SYSTEM); 734 mStorage.setString(REBOOT_ESCROW_KEY_OTHER_VBMETA_DIGEST, 735 mInjector.getVbmetaDigest(true), USER_SYSTEM); 736 mStorage.setInt(REBOOT_ESCROW_KEY_PROVIDER, actualProviderType, USER_SYSTEM); 737 mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); 738 739 return ARM_REBOOT_ERROR_NONE; 740 } 741 setRebootEscrowReady(boolean ready)742 private void setRebootEscrowReady(boolean ready) { 743 if (mRebootEscrowReady != ready) { 744 mRebootEscrowListener.onPreparedForReboot(ready); 745 } 746 mRebootEscrowReady = ready; 747 } 748 prepareRebootEscrow()749 boolean prepareRebootEscrow() { 750 clearRebootEscrowIfNeeded(); 751 if (mInjector.createRebootEscrowProviderIfNeeded() == null) { 752 Slog.w(TAG, "No reboot escrow provider, skipping resume on reboot preparation."); 753 return false; 754 } 755 756 mRebootEscrowWanted = true; 757 mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF); 758 return true; 759 } 760 clearRebootEscrow()761 boolean clearRebootEscrow() { 762 clearRebootEscrowIfNeeded(); 763 return true; 764 } 765 setRebootEscrowListener(RebootEscrowListener listener)766 void setRebootEscrowListener(RebootEscrowListener listener) { 767 mRebootEscrowListener = listener; 768 } 769 770 @VisibleForTesting 771 public static class RebootEscrowEvent { 772 static final int FOUND_ESCROW_DATA = 1; 773 static final int SET_ARMED_STATUS = 2; 774 static final int CLEARED_LSKF_REQUEST = 3; 775 static final int RETRIEVED_STORED_KEK = 4; 776 static final int REQUESTED_LSKF = 5; 777 static final int STORED_LSKF_FOR_USER = 6; 778 static final int RETRIEVED_LSKF_FOR_USER = 7; 779 780 final int mEventId; 781 final Integer mUserId; 782 final long mWallTime; 783 final long mTimestamp; 784 RebootEscrowEvent(int eventId)785 RebootEscrowEvent(int eventId) { 786 this(eventId, null); 787 } 788 RebootEscrowEvent(int eventId, Integer userId)789 RebootEscrowEvent(int eventId, Integer userId) { 790 mEventId = eventId; 791 mUserId = userId; 792 mTimestamp = SystemClock.uptimeMillis(); 793 mWallTime = System.currentTimeMillis(); 794 } 795 getEventDescription()796 String getEventDescription() { 797 switch (mEventId) { 798 case FOUND_ESCROW_DATA: 799 return "Found escrow data"; 800 case SET_ARMED_STATUS: 801 return "Set armed status"; 802 case CLEARED_LSKF_REQUEST: 803 return "Cleared request for LSKF"; 804 case RETRIEVED_STORED_KEK: 805 return "Retrieved stored KEK"; 806 case REQUESTED_LSKF: 807 return "Requested LSKF"; 808 case STORED_LSKF_FOR_USER: 809 return "Stored LSKF for user"; 810 case RETRIEVED_LSKF_FOR_USER: 811 return "Retrieved LSKF for user"; 812 default: 813 return "Unknown event ID " + mEventId; 814 } 815 } 816 } 817 818 @VisibleForTesting 819 public static class RebootEscrowEventLog { 820 private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16]; 821 private int mNextIndex = 0; 822 addEntry(int eventId)823 void addEntry(int eventId) { 824 addEntryInternal(new RebootEscrowEvent(eventId)); 825 } 826 addEntry(int eventId, int userId)827 void addEntry(int eventId, int userId) { 828 addEntryInternal(new RebootEscrowEvent(eventId, userId)); 829 } 830 addEntryInternal(RebootEscrowEvent event)831 private void addEntryInternal(RebootEscrowEvent event) { 832 final int index = mNextIndex; 833 mEntries[index] = event; 834 mNextIndex = (mNextIndex + 1) % mEntries.length; 835 } 836 dump(@onNull IndentingPrintWriter pw)837 void dump(@NonNull IndentingPrintWriter pw) { 838 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); 839 840 for (int i = 0; i < mEntries.length; ++i) { 841 RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length]; 842 if (event == null) { 843 continue; 844 } 845 846 pw.print("Event #"); 847 pw.println(i); 848 849 pw.println(" time=" + sdf.format(new Date(event.mWallTime)) 850 + " (timestamp=" + event.mTimestamp + ")"); 851 852 pw.print(" event="); 853 pw.println(event.getEventDescription()); 854 855 if (event.mUserId != null) { 856 pw.print(" user="); 857 pw.println(event.mUserId); 858 } 859 } 860 } 861 } 862 dump(@onNull IndentingPrintWriter pw)863 void dump(@NonNull IndentingPrintWriter pw) { 864 pw.print("mRebootEscrowWanted="); 865 pw.println(mRebootEscrowWanted); 866 867 pw.print("mRebootEscrowReady="); 868 pw.println(mRebootEscrowReady); 869 870 pw.print("mRebootEscrowListener="); 871 pw.println(mRebootEscrowListener); 872 873 boolean keySet; 874 synchronized (mKeyGenerationLock) { 875 keySet = mPendingRebootEscrowKey != null; 876 } 877 878 pw.print("mPendingRebootEscrowKey is "); 879 pw.println(keySet ? "set" : "not set"); 880 881 RebootEscrowProviderInterface provider = mInjector.getRebootEscrowProvider(); 882 String providerType = provider == null ? "null" : String.valueOf(provider.getType()); 883 pw.print("RebootEscrowProvider type is " + providerType); 884 885 pw.println(); 886 pw.println("Event log:"); 887 pw.increaseIndent(); 888 mEventLog.dump(pw); 889 pw.println(); 890 pw.decreaseIndent(); 891 } 892 } 893