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

Commit b2375947 authored by Adrian Roos's avatar Adrian Roos
Browse files

FRP: Explicitly throw UnsupportedOperation when FRP is not supported

Changes KeyguardManager.createConfirmFactoryResetCredentialIntent such that
it throws UnsupportedOperationException when credential-based FRP is not
available on the device (either because storage was corrupted, or the device
simply does not support it).

This allows GMScore to distinguish this case from when the previous owner
simply didn't set up security.

Also fixes a few places where we previously unintentionally crashed with an
NPE.

Bug: 72368658
Test: atest LockSettingsStorageTests
Change-Id: I92fe1d4b06834e76a4bfffad41276ca28c68ce70
parent a8c77948
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -167,10 +167,11 @@ public class KeyguardManager {
     *                             clicking this button, the activity returns
     *                             {@link #RESULT_ALTERNATE}
     *
     * @return  the intent for launching the activity or null if the credential of the previous
     * owner can not be verified (e.g. because there was none, or the device does not support
     * verifying credentials after a factory reset, or device setup has already been completed).
     *
     * @return the intent for launching the activity or null if the previous owner of the device
     *         did not set a credential.
     * @throws UnsupportedOperationException if the device does not support factory reset
     *                                       credentials
     * @throws IllegalStateException if the device has already been provisioned
     * @hide
     */
    @SystemApi
@@ -178,14 +179,14 @@ public class KeyguardManager {
            CharSequence title, CharSequence description, CharSequence alternateButtonLabel) {
        if (!LockPatternUtils.frpCredentialEnabled(mContext)) {
            Log.w(TAG, "Factory reset credentials not supported.");
            return null;
            throw new UnsupportedOperationException("not supported on this device");
        }

        // Cannot verify credential if the device is provisioned
        if (Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
            Log.e(TAG, "Factory reset credential cannot be verified after provisioning.");
            return null;
            throw new IllegalStateException("must not be provisioned yet");
        }

        // Make sure we have a credential
@@ -194,8 +195,10 @@ public class KeyguardManager {
                    ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE));
            if (pdb == null) {
                Log.e(TAG, "No persistent data block service");
                return null;
                throw new UnsupportedOperationException("not supported on this device");
            }
            // The following will throw an UnsupportedOperationException if the device does not
            // support factory reset credentials (or something went wrong retrieving it).
            if (!pdb.hasFrpCredentialHandle()) {
                Log.i(TAG, "The persistent data block does not have a factory reset credential.");
                return null;
+5 −1
Original line number Diff line number Diff line
@@ -24,7 +24,11 @@ public interface PersistentDataBlockManagerInternal {
    /** Stores the handle to a lockscreen credential to be used for Factory Reset Protection. */
    void setFrpCredentialHandle(byte[] handle);

    /** Retrieves handle to a lockscreen credential to be used for Factory Reset Protection. */
    /**
     * Retrieves handle to a lockscreen credential to be used for Factory Reset Protection.
     *
     * @throws IllegalStateException if the underlying storage is corrupt or inaccessible.
     */
    byte[] getFrpCredentialHandle();

    /** Update the OEM unlock enabled bit, bypassing user restriction checks. */
+10 −6
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Log;
import android.util.Slog;

import com.android.internal.R;
@@ -582,7 +583,12 @@ public class PersistentDataBlockService extends SystemService {
        @Override
        public boolean hasFrpCredentialHandle() {
            enforcePersistentDataBlockAccess();
            try {
                return mInternalService.getFrpCredentialHandle() != null;
            } catch (IllegalStateException e) {
                Slog.e(TAG, "error reading frp handle", e);
                throw new UnsupportedOperationException("cannot read frp credential");
            }
        }
    };

@@ -638,7 +644,7 @@ public class PersistentDataBlockService extends SystemService {
        @Override
        public byte[] getFrpCredentialHandle() {
            if (!enforceChecksumValidity()) {
                return null;
                throw new IllegalStateException("invalid checksum");
            }

            DataInputStream inputStream;
@@ -646,8 +652,7 @@ public class PersistentDataBlockService extends SystemService {
                inputStream = new DataInputStream(
                        new FileInputStream(new File(mDataBlockFile)));
            } catch (FileNotFoundException e) {
                Slog.e(TAG, "partition not available");
                return null;
                throw new IllegalStateException("frp partition not available");
            }

            try {
@@ -662,8 +667,7 @@ public class PersistentDataBlockService extends SystemService {
                    return bytes;
                }
            } catch (IOException e) {
                Slog.e(TAG, "unable to access persistent partition", e);
                return null;
                throw new IllegalStateException("frp handle not readable", e);
            } finally {
                IoUtils.closeQuietly(inputStream);
            }
+8 −3
Original line number Diff line number Diff line
@@ -627,7 +627,12 @@ class LockSettingsStorage {
        if (persistentDataBlock == null) {
            return PersistentData.NONE;
        }
        try {
            return PersistentData.fromBytes(persistentDataBlock.getFrpCredentialHandle());
        } catch (IllegalStateException e) {
            Slog.e(TAG, "Error reading persistent data block", e);
            return PersistentData.NONE;
        }
    }

    public static class PersistentData {
@@ -670,11 +675,11 @@ class LockSettingsStorage {
                    return new PersistentData(type, userId, qualityForUi, payload);
                } else {
                    Slog.wtf(TAG, "Unknown PersistentData version code: " + version);
                    return null;
                    return NONE;
                }
            } catch (IOException e) {
                Slog.wtf(TAG, "Could not parse PersistentData", e);
                return null;
                return NONE;
            }
        }

+8 −0
Original line number Diff line number Diff line
@@ -18,11 +18,14 @@ package com.android.server.locksettings;

import android.content.Context;

import com.android.server.PersistentDataBlockManagerInternal;

import java.io.File;

public class LockSettingsStorageTestable extends LockSettingsStorage {

    public File mStorageDir;
    public PersistentDataBlockManagerInternal mPersistentDataBlock;

    public LockSettingsStorageTestable(Context context, File storageDir) {
        super(context);
@@ -53,6 +56,11 @@ public class LockSettingsStorageTestable extends LockSettingsStorage {
                userId).getAbsolutePath());
    }

    @Override
    public PersistentDataBlockManagerInternal getPersistentDataBlock() {
        return mPersistentDataBlock;
    }

    private File makeDirs(File baseDir, String filePath) {
        File path = new File(filePath);
        if (path.getParent() == null) {
Loading