Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60edeec0 authored by Tianjie Xu's avatar Tianjie Xu Committed by Gerrit Code Review
Browse files

Merge "Delay loadEscrowData from locksettings"

parents 3faed136 1c98980d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -280,6 +280,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            super.onBootPhase(phase);
            if (phase == PHASE_ACTIVITY_MANAGER_READY) {
                mLockSettingsService.migrateOldDataAfterSystemReady();
                mLockSettingsService.loadEscrowData();
            }
        }

@@ -832,11 +833,15 @@ public class LockSettingsService extends ILockSettings.Stub {
        mSpManager.initWeaverService();
        getAuthSecretHal();
        mDeviceProvisionedObserver.onSystemReady();
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable();

        // TODO: maybe skip this for split system user mode.
        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
    }

    private void loadEscrowData() {
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler);
    }

    private void getAuthSecretHal() {
        try {
            mAuthSecretService = IAuthSecret.getService(/* retry */ true);
+68 −8
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -39,6 +40,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

import javax.crypto.SecretKey;

@@ -75,6 +77,13 @@ class RebootEscrowManager {
     */
    private static final int BOOT_COUNT_TOLERANCE = 5;

    /**
     * The default retry specs for loading reboot escrow data. We will attempt to retry loading
     * escrow data on temporarily errors, e.g. unavailable network.
     */
    private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT = 3;
    private static final int DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS = 30;

    /**
     * Logs events for later debugging in bugreports.
     */
@@ -148,6 +157,14 @@ class RebootEscrowManager {
            return null;
        }

        void post(Handler handler, Runnable runnable) {
            handler.post(runnable);
        }

        void postDelayed(Handler handler, Runnable runnable, long delayMillis) {
            handler.postDelayed(runnable, delayMillis);
        }

        public Context getContext() {
            return mContext;
        }
@@ -199,7 +216,18 @@ class RebootEscrowManager {
        mKeyStoreManager = injector.getKeyStoreManager();
    }

    void loadRebootEscrowDataIfAvailable() {
    private void onGetRebootEscrowKeyFailed(List<UserInfo> users) {
        Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
        for (UserInfo user : users) {
            mStorage.removeRebootEscrow(user.id);
        }

        // Clear the old key in keystore.
        mKeyStoreManager.clearKeyStoreEncryptionKey();
        onEscrowRestoreComplete(false);
    }

    void loadRebootEscrowDataIfAvailable(Handler retryHandler) {
        List<UserInfo> users = mUserManager.getUsers();
        List<UserInfo> rebootEscrowUsers = new ArrayList<>();
        for (UserInfo user : users) {
@@ -212,17 +240,49 @@ class RebootEscrowManager {
            return;
        }

        mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry(
                retryHandler, 0, users, rebootEscrowUsers));
    }

    void scheduleLoadRebootEscrowDataOrFail(Handler retryHandler, int attemptNumber,
            List<UserInfo> users, List<UserInfo> rebootEscrowUsers) {
        Objects.requireNonNull(retryHandler);

        final int retryLimit = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA,
                "load_escrow_data_retry_count", DEFAULT_LOAD_ESCROW_DATA_RETRY_COUNT);
        final int retryIntervalInSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_OTA,
                "load_escrow_data_retry_interval_seconds",
                DEFAULT_LOAD_ESCROW_DATA_RETRY_INTERVAL_SECONDS);

        if (attemptNumber < retryLimit) {
            Slog.i(TAG, "Scheduling loadRebootEscrowData retry number: " + attemptNumber);
            mInjector.postDelayed(retryHandler, () -> loadRebootEscrowDataWithRetry(
                    retryHandler, attemptNumber, users, rebootEscrowUsers),
                    retryIntervalInSeconds * 1000);
            return;
        }

        Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts");
        onGetRebootEscrowKeyFailed(users);
    }

    void loadRebootEscrowDataWithRetry(Handler retryHandler, int attemptNumber,
            List<UserInfo> users, List<UserInfo> rebootEscrowUsers) {
        // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is
        // generated before reboot. Note that we will clear the escrow key even if the keystore key
        // is null.
        SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey();
        RebootEscrowKey escrowKey = getAndClearRebootEscrowKey(kk);
        if (kk == null || escrowKey == null) {
            Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
            for (UserInfo user : users) {
                mStorage.removeRebootEscrow(user.id);
        RebootEscrowKey escrowKey;
        try {
            escrowKey = getAndClearRebootEscrowKey(kk);
        } catch (IOException e) {
            scheduleLoadRebootEscrowDataOrFail(retryHandler, attemptNumber + 1, users,
                    rebootEscrowUsers);
            return;
        }
            onEscrowRestoreComplete(false);

        if (kk == null || escrowKey == null) {
            onGetRebootEscrowKeyFailed(users);
            return;
        }

@@ -249,7 +309,7 @@ class RebootEscrowManager {
        }
    }

    private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) {
    private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) throws IOException {
        RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
        if (rebootEscrowProvider == null) {
            Slog.w(TAG,
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import javax.crypto.SecretKey;
 * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL.
 */
class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface {
    private static final String TAG = "RebootEscrowProvider";
    private static final String TAG = "RebootEscrowProviderHal";

    private final Injector mInjector;

+5 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.locksettings;

import java.io.IOException;

import javax.crypto.SecretKey;

/**
@@ -33,9 +35,10 @@ public interface RebootEscrowProviderInterface {

    /**
     * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted,
     * use the input key to decrypt the RebootEscrowKey. Returns null on failure.
     * use the input key to decrypt the RebootEscrowKey. Returns null on failure. Throws an
     * IOException if the failure is non-fatal, and a retry may succeed.
     */
    RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey);
    RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException;

    /**
     * Clears the stored RebootEscrowKey.
+11 −6
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import javax.crypto.SecretKey;
 * encrypt & decrypt the blob.
 */
class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterface {
    private static final String TAG = "RebootEscrowProvider";
    private static final String TAG = "RebootEscrowProviderServerBased";

    // Timeout for service binding
    private static final long DEFAULT_SERVICE_TIMEOUT_IN_SECONDS = 10;
@@ -50,6 +50,8 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa

    private final Injector mInjector;

    private byte[] mServerBlob;

    static class Injector {
        private ResumeOnRebootServiceConnection mServiceConnection = null;

@@ -124,17 +126,20 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa
    }

    @Override
    public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) {
        byte[] serverBlob = mStorage.readRebootEscrowServerBlob();
    public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) throws IOException {
        if (mServerBlob == null) {
            mServerBlob = mStorage.readRebootEscrowServerBlob();
        }
        // Delete the server blob in storage.
        mStorage.removeRebootEscrowServerBlob();
        if (serverBlob == null) {
        if (mServerBlob == null) {
            Slog.w(TAG, "Failed to read reboot escrow server blob from storage");
            return null;
        }

        Slog.i(TAG, "Loaded reboot escrow server blob from storage");
        try {
            byte[] escrowKeyBytes = unwrapServerBlob(serverBlob, decryptionKey);
            byte[] escrowKeyBytes = unwrapServerBlob(mServerBlob, decryptionKey);
            if (escrowKeyBytes == null) {
                Slog.w(TAG, "Decrypted reboot escrow key bytes should not be null");
                return null;
@@ -145,7 +150,7 @@ class RebootEscrowProviderServerBasedImpl implements RebootEscrowProviderInterfa
            }

            return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
        } catch (TimeoutException | RemoteException | IOException e) {
        } catch (TimeoutException | RemoteException e) {
            Slog.w(TAG, "Failed to decrypt the server blob ", e);
            return null;
        }
Loading