Loading core/java/android/util/FeatureFlagUtils.java +8 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,13 @@ public class FeatureFlagUtils { public static final String SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS = "settings_show_udfps_enroll_in_settings"; /** * Flag to enable lock screen credentials transfer API in Android U. * @hide */ public static final String SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API = "settings_enable_lockscreen_transfer_api"; private static final Map<String, String> DEFAULT_FLAGS; static { Loading Loading @@ -207,6 +214,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false"); DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false"); DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false"); } private static final Set<String> PERSISTENT_FLAGS; Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +23 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.FeatureFlagUtils; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -2503,6 +2504,28 @@ public class LockSettingsService extends ILockSettings.Stub { return mRecoverableKeyStoreManager.getKey(alias); } /** * Starts a session to verify lock screen credentials provided by a remote device. */ public void startRemoteLockscreenValidation() { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) { throw new UnsupportedOperationException("Under development"); } mRecoverableKeyStoreManager.startRemoteLockscreenValidation(); } /** * Verifies credentials guess from a remote device. */ public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) { throw new UnsupportedOperationException("Under development"); } mRecoverableKeyStoreManager.validateRemoteLockscreen(encryptedCredential); } // Reading these settings needs the contacts permission private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] { Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, Loading services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +29 −0 Original line number Diff line number Diff line Loading @@ -965,6 +965,35 @@ public class RecoverableKeyStoreManager { } } /** * Starts a session to verify lock screen credentials provided by a remote device. */ public void startRemoteLockscreenValidation() { checkVerifyRemoteLockscreenPermission(); // TODO(b/254335492): Create session in memory return; } /** * Verifies encrypted credentials guess from a remote device. */ public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) { checkVerifyRemoteLockscreenPermission(); // TODO(b/254335492): Decrypt and verify credentials return; } private void checkVerifyRemoteLockscreenPermission() { // TODO(b/254335492): Check new system permission mContext.enforceCallingOrSelfPermission( Manifest.permission.RECOVER_KEYSTORE, "Caller " + Binder.getCallingUid() + " doesn't have verifyRemoteLockscreen permission."); int userId = UserHandle.getCallingUserId(); int uid = Binder.getCallingUid(); mCleanupManager.registerRecoveryAgent(userId, uid); } private void checkRecoverKeyStorePermission() { mContext.enforceCallingOrSelfPermission( Manifest.permission.RECOVER_KEYSTORE, Loading services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.locksettings.recoverablekeystore.storage; import android.annotation.Nullable; import android.util.SparseArray; import java.security.KeyPair; /** * Memory based storage for keyPair used to send encrypted credentials from a remote device. * * @hide */ public class RemoteLockscreenValidationSessionStorage { private final SparseArray<LockScreenVerificationSession> mSessionsByUserId = new SparseArray<>(); /** * Returns session for given user or null. * * @param userId The user id * @return The session info. * * @hide */ @Nullable public LockScreenVerificationSession get(int userId) { return mSessionsByUserId.get(userId); } /** * Creates a new session to verify lockscreen credentials guess. * * Session will be automatically removed after 10 minutes of inactivity. * @param userId The user id * * @hide */ public LockScreenVerificationSession startSession(int userId) { if (mSessionsByUserId.get(userId) != null) { mSessionsByUserId.remove(userId); } LockScreenVerificationSession newSession = null; // TODO(b/254335492): Schedule a task to remove session. mSessionsByUserId.put(userId, newSession); return newSession; } /** * Deletes session for a user. */ public void remove(int userId) { mSessionsByUserId.remove(userId); } /** * Holder for keypair used by remote lock screen validation. * * @hide */ public static class LockScreenVerificationSession { private final KeyPair mKeyPair; private final long mSessionStartTimeMillis; /** * @hide */ public LockScreenVerificationSession(KeyPair keyPair, long sessionStartTimeMillis) { mKeyPair = keyPair; mSessionStartTimeMillis = sessionStartTimeMillis; } } } Loading
core/java/android/util/FeatureFlagUtils.java +8 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,13 @@ public class FeatureFlagUtils { public static final String SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS = "settings_show_udfps_enroll_in_settings"; /** * Flag to enable lock screen credentials transfer API in Android U. * @hide */ public static final String SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API = "settings_enable_lockscreen_transfer_api"; private static final Map<String, String> DEFAULT_FLAGS; static { Loading Loading @@ -207,6 +214,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false"); DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false"); DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false"); } private static final Set<String> PERSISTENT_FLAGS; Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +23 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.FeatureFlagUtils; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -2503,6 +2504,28 @@ public class LockSettingsService extends ILockSettings.Stub { return mRecoverableKeyStoreManager.getKey(alias); } /** * Starts a session to verify lock screen credentials provided by a remote device. */ public void startRemoteLockscreenValidation() { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) { throw new UnsupportedOperationException("Under development"); } mRecoverableKeyStoreManager.startRemoteLockscreenValidation(); } /** * Verifies credentials guess from a remote device. */ public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) { throw new UnsupportedOperationException("Under development"); } mRecoverableKeyStoreManager.validateRemoteLockscreen(encryptedCredential); } // Reading these settings needs the contacts permission private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] { Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +29 −0 Original line number Diff line number Diff line Loading @@ -965,6 +965,35 @@ public class RecoverableKeyStoreManager { } } /** * Starts a session to verify lock screen credentials provided by a remote device. */ public void startRemoteLockscreenValidation() { checkVerifyRemoteLockscreenPermission(); // TODO(b/254335492): Create session in memory return; } /** * Verifies encrypted credentials guess from a remote device. */ public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) { checkVerifyRemoteLockscreenPermission(); // TODO(b/254335492): Decrypt and verify credentials return; } private void checkVerifyRemoteLockscreenPermission() { // TODO(b/254335492): Check new system permission mContext.enforceCallingOrSelfPermission( Manifest.permission.RECOVER_KEYSTORE, "Caller " + Binder.getCallingUid() + " doesn't have verifyRemoteLockscreen permission."); int userId = UserHandle.getCallingUserId(); int uid = Binder.getCallingUid(); mCleanupManager.registerRecoveryAgent(userId, uid); } private void checkRecoverKeyStorePermission() { mContext.enforceCallingOrSelfPermission( Manifest.permission.RECOVER_KEYSTORE, Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.locksettings.recoverablekeystore.storage; import android.annotation.Nullable; import android.util.SparseArray; import java.security.KeyPair; /** * Memory based storage for keyPair used to send encrypted credentials from a remote device. * * @hide */ public class RemoteLockscreenValidationSessionStorage { private final SparseArray<LockScreenVerificationSession> mSessionsByUserId = new SparseArray<>(); /** * Returns session for given user or null. * * @param userId The user id * @return The session info. * * @hide */ @Nullable public LockScreenVerificationSession get(int userId) { return mSessionsByUserId.get(userId); } /** * Creates a new session to verify lockscreen credentials guess. * * Session will be automatically removed after 10 minutes of inactivity. * @param userId The user id * * @hide */ public LockScreenVerificationSession startSession(int userId) { if (mSessionsByUserId.get(userId) != null) { mSessionsByUserId.remove(userId); } LockScreenVerificationSession newSession = null; // TODO(b/254335492): Schedule a task to remove session. mSessionsByUserId.put(userId, newSession); return newSession; } /** * Deletes session for a user. */ public void remove(int userId) { mSessionsByUserId.remove(userId); } /** * Holder for keypair used by remote lock screen validation. * * @hide */ public static class LockScreenVerificationSession { private final KeyPair mKeyPair; private final long mSessionStartTimeMillis; /** * @hide */ public LockScreenVerificationSession(KeyPair keyPair, long sessionStartTimeMillis) { mKeyPair = keyPair; mSessionStartTimeMillis = sessionStartTimeMillis; } } }