From dae8db3eb2d059ea06b8c658ffd7397f6e4d2748 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Wed, 25 Nov 2020 14:33:04 -0800 Subject: [PATCH] Introduce new App Ops permission USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER Bug: 174263375 Test: `atest android.telephony.cts.TelephonyManagerTest#testTelephonyManager` pass on crosshatch Change-Id: Ic0e919d953be0422bf78477b8de13691b25b6cc3 --- core/api/current.txt | 1 + core/api/test-current.txt | 1 + core/java/android/app/AppOpsManager.java | 24 +++++++++- core/res/AndroidManifest.xml | 7 +++ .../telephony/TelephonyPermissions.java | 36 +++++++++++++- .../android/telephony/TelephonyManager.java | 48 +++++++------------ .../internal/telephony/IPhoneSubInfo.aidl | 3 +- 7 files changed, 85 insertions(+), 35 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 14c1dc873650d..c6f0f33081006 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -165,6 +165,7 @@ package android { field public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC"; field @Deprecated public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT"; field public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT"; + field public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"; field public static final String USE_SIP = "android.permission.USE_SIP"; field public static final String VIBRATE = "android.permission.VIBRATE"; field public static final String WAKE_LOCK = "android.permission.WAKE_LOCK"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index ffb31c9fe5733..12531976d90ef 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -216,6 +216,7 @@ package android.app { field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time"; field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time"; field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls"; + field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier"; field public static final int OP_COARSE_LOCATION = 0; // 0x0 field public static final int OP_RECORD_AUDIO = 27; // 0x1b field public static final int OP_START_FOREGROUND = 76; // 0x4c diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 4dd6a7efe7c53..f60f569be8922 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1165,9 +1165,13 @@ public class AppOpsManager { */ public static final int OP_MANAGE_CREDENTIALS = AppProtoEnums.APP_OP_MANAGE_CREDENTIALS; + /** @hide */ + public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = + AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int _NUM_OP = 105; + public static final int _NUM_OP = 106; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -1525,6 +1529,15 @@ public class AppOpsManager { */ public static final String OPSTR_MANAGE_CREDENTIALS = "android:manage_credentials"; + /** + * Allows to read device identifiers and use ICC based authentication like EAP-AKA. + * + * @hide + */ + @TestApi + public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = + "android:use_icc_auth_with_device_identifier"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -1604,6 +1617,7 @@ public class AppOpsManager { OP_INTERACT_ACROSS_PROFILES, OP_LOADER_USAGE_STATS, OP_MANAGE_ONGOING_CALLS, + OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -1720,6 +1734,7 @@ public class AppOpsManager { OP_RECORD_AUDIO_HOTWORD, // RECORD_AUDIO_HOTWORD OP_MANAGE_ONGOING_CALLS, // MANAGE_ONGOING_CALLS OP_MANAGE_CREDENTIALS, // MANAGE_CREDENTIALS + OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -1831,6 +1846,7 @@ public class AppOpsManager { OPSTR_RECORD_AUDIO_HOTWORD, OPSTR_MANAGE_ONGOING_CALLS, OPSTR_MANAGE_CREDENTIALS, + OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -1943,6 +1959,7 @@ public class AppOpsManager { "RECORD_AUDIO_HOTWORD", "MANAGE_ONGOING_CALLS", "MANAGE_CREDENTIALS", + "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER", }; /** @@ -2056,6 +2073,7 @@ public class AppOpsManager { null, // no permission for OP_RECORD_AUDIO_HOTWORD Manifest.permission.MANAGE_ONGOING_CALLS, null, // no permission for OP_MANAGE_CREDENTIALS + Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, }; /** @@ -2169,6 +2187,7 @@ public class AppOpsManager { null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS + null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2281,6 +2300,7 @@ public class AppOpsManager { null, // RECORD_AUDIO_HOTWORD null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS + null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2392,6 +2412,7 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS + AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** @@ -2507,6 +2528,7 @@ public class AppOpsManager { false, // RECORD_AUDIO_HOTWORD true, // MANAGE_ONGOING_CALLS false, // MANAGE_CREDENTIALS + true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER }; /** diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1250eb776176b..849ab0a4c380d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2212,6 +2212,13 @@ + + + diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 0c463949b14a4..4bb7cc47d702d 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -244,7 +244,9 @@ public final class TelephonyPermissions { *
    *
  • return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges on any active subscription. + * access check, or the calling package has carrier privileges on any active + * subscription, or the calling package has the {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission. *
  • throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission * or carrier privileges of any active subscription. @@ -256,6 +258,10 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { + if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage, + callingFeatureId, message)) { + return true; + } return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( context, subId, callingPackage, callingFeatureId, message, true); } @@ -267,7 +273,9 @@ public final class TelephonyPermissions { *
      *
    • return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier - * access check, or the calling package has carrier privileges on specified subscription. + * access check, or the calling package has carrier privileges on specified subscription, + * or the calling package has the {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} appop permission. *
    • throw SecurityException: if the caller does not meet any of the requirements and is * targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission. *
    • return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE @@ -278,6 +286,10 @@ public final class TelephonyPermissions { */ public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { + if (checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context, callingPackage, + callingFeatureId, message)) { + return true; + } return checkPrivilegedReadPermissionOrCarrierPrivilegePermission( context, subId, callingPackage, callingFeatureId, message, false); } @@ -384,6 +396,26 @@ public final class TelephonyPermissions { + " does not meet the requirements to access device identifiers."); } + /** + * Check whether the caller (or self, if not processing an IPC) has {@link + * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} AppOp permission. + * + *

      With the permission, the caller can access device/subscriber identifiers and use ICC + * authentication like EAP-AKA. + */ + public static boolean checkCallingOrSelfUseIccAuthWithDeviceIdentifier(Context context, + String callingPackage, String callingFeatureId, String message) { + // Cannot perform appop check if the calling package is null + if (callingPackage == null) { + return false; + } + int callingUid = Binder.getCallingUid(); + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int opMode = appOps.noteOpNoThrow(AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, + callingUid, callingPackage, callingFeatureId, message); + return opMode == AppOpsManager.MODE_ALLOWED; + } + /** * Check whether the app with the given pid/uid can read the call log. * @return {@code true} if the specified app has the read call log permission and AppOpp granted diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 239329cb447e8..72d35cf9a502a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2009,6 +2009,8 @@ public class TelephonyManager { * active subscription. *

    • If the calling app is the default SMS role holder (see {@link * RoleManager#isRoleHeld(String)}). + *
    • If the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. *
    * *

    If the calling app does not meet one of these requirements then this method will behave @@ -4019,6 +4021,8 @@ public class TelephonyManager { *

  • If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). *
  • If the calling app is the default SMS role holder (see {@link * RoleManager#isRoleHeld(String)}). + *
  • If the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. *
* *

If the calling app does not meet one of these requirements then this method will behave @@ -4043,33 +4047,8 @@ public class TelephonyManager { * for a subscription. * Return null if it is unavailable. * - *

Starting with API level 29, persistent device identifiers are guarded behind additional - * restrictions, and apps are recommended to use resettable identifiers (see Best practices for unique identifiers). This - * method can be invoked if one of the following requirements is met: - *

    - *
  • If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this - * is a privileged permission that can only be granted to apps preloaded on the device. - *
  • If the calling app is the device or profile owner and has been granted the - * {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that - * owns a managed profile on the device; for more details see Work profiles. - * Profile owner access is deprecated and will be removed in a future release. - *
  • If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). - *
  • If the calling app is the default SMS role holder (see {@link - * RoleManager#isRoleHeld(String)}). - *
- * - *

If the calling app does not meet one of these requirements then this method will behave - * as follows: - * - *

    - *
  • If the calling app's target SDK is API level 28 or lower and the app has the - * READ_PHONE_STATE permission then null is returned.
  • - *
  • If the calling app's target SDK is API level 28 or lower and the app does not have - * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or - * higher, then a SecurityException is thrown.
  • - *
+ * See {@link #getSubscriberId()} for details on the required permissions and behavior + * when the caller does not hold sufficient permissions. * * @param subId whose subscriber id is returned * @hide @@ -7226,8 +7205,13 @@ public class TelephonyManager { * Returns the response of authentication for the default subscription. * Returns null if the authentication hasn't been successful * - *

Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling - * app has carrier privileges (see {@link #hasCarrierPrivileges}). + *

Requires one of the following permissions: + *

    + *
  • READ_PRIVILEGED_PHONE_STATE + *
  • the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + *
  • the calling app has been granted the + * {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} permission. + *
* * @param appType the icc application type, like {@link #APPTYPE_USIM} * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or @@ -7252,7 +7236,8 @@ public class TelephonyManager { * Returns the response of USIM Authentication for specified subId. * Returns null if the authentication hasn't been successful * - *

Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + *

See {@link #getIccAuthentication(int, int, String)} for details on the required + * permissions. * * @param subId subscription ID used for authentication * @param appType the icc application type, like {@link #APPTYPE_USIM} @@ -7275,7 +7260,8 @@ public class TelephonyManager { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) return null; - return info.getIccSimChallengeResponse(subId, appType, authType, data); + return info.getIccSimChallengeResponse(subId, appType, authType, data, + getOpPackageName(), getAttributionTag()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index 09f9b4212c03d..ce2017bb9a35d 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -216,5 +216,6 @@ interface IPhoneSubInfo { * @param data authentication challenge data * @return challenge response */ - String getIccSimChallengeResponse(int subId, int appType, int authType, String data); + String getIccSimChallengeResponse(int subId, int appType, int authType, String data, + String callingPackage, String callingFeatureId); }