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

Commit ee5e5a6b authored by Shawn Willden's avatar Shawn Willden Committed by Android (Google) Code Review
Browse files

Merge "Update LockSettingsService to support hardened FRP" into main

parents 531fb673 19db3fab
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3683,6 +3683,7 @@ package android.content {
    field public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
    field @Deprecated public static final String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
    field public static final String ACTION_LOAD_DATA = "android.intent.action.LOAD_DATA";
    field @FlaggedApi("android.security.frp_enforcement") public static final String ACTION_MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED = "android.intent.action.MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED";
    field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
    field @Deprecated public static final String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
    field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
+21 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.content;
import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
import static android.content.ContentProvider.maybeAddUserId;
import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
import static android.security.Flags.FLAG_FRP_ENFORCEMENT;
import static android.service.chooser.Flags.FLAG_ENABLE_SHARESHEET_METADATA_EXTRA;
import android.Manifest;
@@ -3901,6 +3902,26 @@ public class Intent implements Parcelable, Cloneable {
    public static final String ACTION_IDLE_MAINTENANCE_END =
            "android.intent.action.ACTION_IDLE_MAINTENANCE_END";
    /**
     * Broadcast Action: A broadcast sent to the main user when the main user changes their
     * Lock Screen Knowledge Factor, either because they changed the current value, or because
     * they added or removed it.
     *
     * <p class="note">At present, this intent is only broadcast to listeners with the
     * CONFIGURE_FACTORY_RESET_PROTECTION signature|privileged permiession.</p>
     *
     * <p class="note">This is a protected intent that can only be sent by the system.</p>
     *
     * @hide
     */
    @FlaggedApi(FLAG_FRP_ENFORCEMENT)
    @SystemApi
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    @BroadcastBehavior(protectedBroadcast = true)
    public static final String
            ACTION_MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED =
            "android.intent.action.MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED";
    /**
     * Broadcast Action: a remote intent is to be broadcasted.
     *
+1 −0
Original line number Diff line number Diff line
@@ -836,6 +836,7 @@
    <protected-broadcast android:name="android.intent.action.PROFILE_AVAILABLE" />
    <protected-broadcast android:name="android.intent.action.PROFILE_UNAVAILABLE" />
    <protected-broadcast android:name="android.app.action.CONSOLIDATED_NOTIFICATION_POLICY_CHANGED" />
    <protected-broadcast android:name="android.intent.action.MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED" />

    <!-- ====================================================================== -->
    <!--                          RUNTIME PERMISSIONS                           -->
+30 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.locksettings;

import static android.security.Flags.reportPrimaryAuthAttempts;
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS;
import static android.Manifest.permission.SET_INITIAL_LOCK;
@@ -27,6 +28,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRY
import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_MESSAGE;
import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_TITLE;
import static android.content.Context.KEYGUARD_SERVICE;
import static android.content.Intent.ACTION_MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;
@@ -1201,8 +1203,9 @@ public class LockSettingsService extends ILockSettings.Stub {

        final boolean inSetupWizard = Settings.Secure.getIntForUser(cr,
                Settings.Secure.USER_SETUP_COMPLETE, 0, mainUserId) == 0;
        final boolean secureFrp = Settings.Global.getInt(cr,
                Settings.Global.SECURE_FRP_MODE, 0) == 1;
        final boolean secureFrp = android.security.Flags.frpEnforcement()
                ? mStorage.isFactoryResetProtectionActive()
                : (Settings.Global.getInt(cr, Settings.Global.SECURE_FRP_MODE, 0) == 1);

        if (inSetupWizard && secureFrp) {
            throw new SecurityException("Cannot change credential in SUW while factory reset"
@@ -2332,8 +2335,13 @@ public class LockSettingsService extends ILockSettings.Stub {

        synchronized (mSpManager) {
            if (isSpecialUserId(userId)) {
                return mSpManager.verifySpecialUserCredential(userId, getGateKeeperService(),
                response = mSpManager.verifySpecialUserCredential(userId, getGateKeeperService(),
                        credential, progressCallback);
                if (android.security.Flags.frpEnforcement() && response.isMatched()
                        && userId == USER_FRP) {
                    mStorage.deactivateFactoryResetProtectionWithoutSecret();
                }
                return response;
            }

            long protectorId = getCurrentLskfBasedProtectorId(userId);
@@ -3054,6 +3062,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        setCurrentLskfBasedProtectorId(newProtectorId, userId);
        LockPatternUtils.invalidateCredentialTypeCache();
        synchronizeUnifiedChallengeForProfiles(userId, profilePasswords);
        sendMainUserCredentialChangedNotificationIfNeeded(userId);

        setUserPasswordMetrics(credential, userId);
        mUnifiedProfilePasswordCache.removePassword(userId);
@@ -3071,6 +3080,24 @@ public class LockSettingsService extends ILockSettings.Stub {
        return newProtectorId;
    }

    private void sendMainUserCredentialChangedNotificationIfNeeded(int userId) {
        if (!android.security.Flags.frpEnforcement()) {
            return;
        }

        if (userId != mInjector.getUserManagerInternal().getMainUserId()) {
            return;
        }

        sendBroadcast(new Intent(ACTION_MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED),
                UserHandle.of(userId), CONFIGURE_FACTORY_RESET_PROTECTION);
    }

    @VisibleForTesting
    void sendBroadcast(Intent intent, UserHandle userHandle, String permission) {
        mContext.sendBroadcastAsUser(intent, userHandle, permission, /* options */ null);
    }

    private void removeBiometricsForUser(int userId) {
        removeAllFingerprintForUser(userId);
        removeAllFaceForUser(userId);
+30 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.Environment;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.persistentdata.PersistentDataBlockManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
@@ -587,6 +588,10 @@ class LockSettingsStorage {
        return mPersistentDataBlockManagerInternal;
    }

    /**
     * Writes main user credential handle to the persistent data block, to enable factory reset
     * protection to be deactivated with the credential.
     */
    public void writePersistentDataBlock(int persistentType, int userId, int qualityForUi,
            byte[] payload) {
        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlockManager();
@@ -610,6 +615,31 @@ class LockSettingsStorage {
        }
    }

    public void deactivateFactoryResetProtectionWithoutSecret() {
        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlockManager();
        if (persistentDataBlock != null) {
            persistentDataBlock.deactivateFactoryResetProtectionWithoutSecret();
        } else {
            Slog.wtf(TAG, "Failed to get PersistentDataBlockManagerInternal");
        }
    }

    public boolean isFactoryResetProtectionActive() {
        PersistentDataBlockManager persistentDataBlockManager =
                mContext.getSystemService(PersistentDataBlockManager.class);
        if (persistentDataBlockManager != null) {
            return persistentDataBlockManager.isFactoryResetProtectionActive();
        } else {
            Slog.wtf(TAG, "Failed to get PersistentDataBlockManager");
            // This should never happen, but in the event it does, let's not block the user.  This
            // may be the wrong call, since if an attacker can find a way to prevent us from
            // getting the PersistentDataBlockManager they can defeat FRP, but if they can block
            // access to PersistentDataBlockManager they must have compromised the system and we've
            // probably already lost this battle.
            return false;
        }
    }

    /**
     * Provides a concrete data structure to represent the minimal information from
     * a user's LSKF-based SP protector that is needed to verify the user's LSKF,
Loading