From 2b769285b5c9c719a2decd60b2e7c1faa2042197 Mon Sep 17 00:00:00 2001 From: Dmitry Dementyev Date: Fri, 20 Jan 2023 13:01:31 -0800 Subject: [PATCH] Add flag to guard remote lock screen verification API. Started feature implementation in RecoverableKeyStoreManager. Bug: 254335492 Test: none Change-Id: Ib6006fcaa6fcc84f682cda21755b12d5412fa6d8 --- core/java/android/util/FeatureFlagUtils.java | 8 ++ .../locksettings/LockSettingsService.java | 23 +++++ .../RecoverableKeyStoreManager.java | 29 ++++++ ...oteLockscreenValidationSessionStorage.java | 89 +++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 70b04a15f9f2d..06fe523e17a69 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -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 DEFAULT_FLAGS; static { @@ -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 PERSISTENT_FLAGS; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 31b8ef28f2464..48e0c300979c0 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -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; @@ -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, diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index e620c80b8e285..7c80d8a54bca6 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -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, diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java new file mode 100644 index 0000000000000..7698c28daddb4 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RemoteLockscreenValidationSessionStorage.java @@ -0,0 +1,89 @@ +/* + * 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 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; + } + } +}