Android 10 cambia los permisos de los identificadores de dispositivos para que todos los identificadores de dispositivos ahora estén protegidos por el permiso READ_PRIVILEGED_PHONE_STATE
. Antes de Android 10, los identificadores de dispositivos persistentes (IMEI/MEID, IMSI, SIM y número de serie de compilación) estaban protegidos por el permiso de tiempo de ejecución READ_PHONE_STATE
.
El permiso READ_PRIVILEGED_PHONE_STATE
solo se otorga a las apps firmadas con la clave de plataforma y a las apps del sistema con privilegios.
Puedes encontrar más información sobre los nuevos requisitos de permisos en las páginas de Javadoc de TelephonyManager.java y Build.java.
Este cambio afecta a las siguientes APIs:
- TelephonyManager#getDeviceId
- TelephonyManager#getImei
- TelephonyManager#getMeid
- TelephonyManager#getSimSerialNumber
- TelephonyManager#getSubscriberId
- Build#getSerial
Acceso de las apps del operador sin el permiso READ_PRIVILEGED_PHONE_STATE
Las apps de operadores precargadas que no califican para el permiso READ_PRIVILEGED_PHONE_STATE
pueden implementar una de las opciones de la siguiente tabla.
Opción | Descripción | Limitaciones |
---|---|---|
Privilegios de operador de UICC | La plataforma de Android carga los certificados almacenados en la UICC y otorga permiso a las apps firmadas por estos certificados para realizar llamadas a métodos especiales. | Los operadores heredados tienen una gran cantidad establecida de SIM, que no se puede actualizar fácilmente. Además, los operadores que no tienen derechos de autoría para las SIM nuevas (por ejemplo, los MVNO que tienen SIM emitidas por MNO) no pueden agregar ni actualizar certificados en las SIM. |
Lista de entidades permitidas de OEM | Los OEMs pueden usar OP_READ_DEVICE_IDENTIFIER para proporcionar identificadores de dispositivos a las apps del operador incluidas en la lista de entidades permitidas. |
Esta solución no es escalable para todos los operadores. |
Código de asignación de tipo (TAC) | Usa el método getTypeAllocationCode , que se introdujo en Android 10, para exponer el TAC que muestra la información del fabricante y el modelo. |
La información del TAC no es adecuada para identificar un dispositivo específico. |
MSISDN | Los operadores pueden usar el número de teléfono (MSISDN), disponible en TelephonyManager con el grupo de permisos PHONE , para buscar el IMEI en sus sistemas de backend. |
Esto requiere una inversión significativa para las empresas de transporte. Los operadores que asignan sus claves de red con IMSI requieren recursos técnicos significativos para cambiar a MSISDN. |
Todas las apps del operador pueden acceder a los identificadores de dispositivos actualizando el archivo CarrierConfig.xml
con el hash del certificado de firma de la app del operador. Cuando la app del operador llama a un método para leer información privilegiada, la plataforma busca una coincidencia del hash del certificado de firma de la app (firma SHA-1 o SHA-256 del certificado) en el archivo CarrierConfig.xml
. Si se encuentra una coincidencia, se muestra la información solicitada. Si no se encuentra ninguna coincidencia, se muestra una excepción de seguridad.
Para implementar esta solución, los operadores DEBEN seguir estos pasos:
- Actualiza
CarrierConfig.xml
con el hash del certificado de firma de la app del operador y envía un parche. - Solicita a los OEMs que actualicen su compilación con QPR1 o versiones posteriores (recomendado) O estos parches de plataforma obligatorios y el parche que contiene el archivo
CarrierConfig.xml
actualizado del paso 1 anterior.
Implementación
Actualiza la lista de entidades permitidas de permisos con privilegios para otorgar el permiso READ_PRIVILEGED_PHONE_STATE
a aquellas apps con privilegios que requieren acceso a los identificadores de dispositivos.
Para obtener más información sobre las listas de entidades permitidas, consulta Inclusión de permisos con privilegios en la lista blanca.
Para invocar las APIs afectadas, una app debe cumplir con uno de los siguientes requisitos:
- Si la app es una app con privilegios cargada previamente, necesita el permiso
READ_PRIVILEGED_PHONE_STATE
declarado en AndroidManifest.xml. La app también debe incluir en la lista de entidades permitidas este permiso con privilegios. - Las apps que se entregan a través de Google Play necesitan privilegios de operador. Obtén más información para otorgar privilegios de operador en la página Privilegios de operador de UICC.
- Una app del propietario del dispositivo o del perfil a la que se le otorgó el permiso
READ_PHONE_STATE
Una app que no cumple con ninguno de estos requisitos tiene el siguiente comportamiento:
- Si la app se orienta a versiones anteriores a Q y no tiene el permiso
READ_PHONE_STATE
otorgado, se activaSecurityException
. Este es el comportamiento actual anterior a Q, ya que este permiso es obligatorio para invocar estas APIs. - Si la app se orienta a versiones anteriores a Q y tiene el permiso
READ_PHONE_STATE
otorgado, recibe un valor nulo para todas las APIs de TelephonyManager yBuild.UNKNOWN
para el métodoBuild#getSerial
. - Si la app se orienta a Android 10 o versiones posteriores y no cumple con ninguno de los requisitos nuevos, recibirá una SecurityException.
Validación y pruebas
El conjunto de pruebas de compatibilidad (CTS) incluye pruebas para verificar el comportamiento esperado de acceso al identificador de dispositivo para apps con privilegios de operador, propietarios de dispositivos y perfiles, y aquellas apps que no deberían tener acceso a los identificadores de dispositivos.
Las siguientes pruebas de CTS son específicas de esta función.
cts-tradefed run cts -m CtsCarrierApiTestCases -t android.carrierapi.cts.CarrierApiTest
cts-tradefed run cts -m CtsTelephonyTestCases -t android.telephony.cts.TelephonyManagerTest
cts-tradefed run cts -m CtsTelephony3TestCases
cts-tradefed run cts -m CtsPermissionTestCases -t android.permission.cts.TelephonyManagerPermissionTest
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifiers
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifiers
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCannotGetDeviceIdentifiersWithoutPermission
cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCannotGetDeviceIdentifiersWithoutPermission
Preguntas frecuentes
¿Cuántas apps se pueden incluir en la lista de entidades permitidas en CarrierConfig.xml
para un (MCC, MNC) determinado?
No hay límite para la cantidad de hashes de certificados incluidos en el array.
¿Qué parámetros de CarrierConfig en CarrierConfig.xml
debo usar para que una app esté en la lista de entidades permitidas?
Usa el siguiente elemento de configuración de nivel superior dentro del CarrierConfig.xml
específico de las opciones de AOSP que estás configurando:
<string-array name="carrier_certificate_string_array" num="2"> <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/> <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/> </string-array>
¿Hay una plantilla de CarrierConfig base que pueda usar?
Usa la siguiente plantilla. Se debe agregar al recurso relevante.
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <carrier_config> <string-array name="carrier_certificate_string_array" num="1"> <item value="CERTIFICATE_HASH_HERE"/> </string-array> </carrier_config>
¿La SIM del operador debe estar en el dispositivo para acceder a los identificadores del dispositivo?
El CarrierConfig.xml
que se usa se determina en función de la SIM que se inserta actualmente. Esto significa que, si la app del operador X intenta obtener privilegios de acceso mientras se inserta la SIM del operador Y, el dispositivo no encontrará una coincidencia para el hash y mostrará una excepción de seguridad.
En los dispositivos con varias SIM, el operador n° 1 solo tiene privilegios de acceso para la SIM n° 1 y viceversa.
¿Cómo los operadores convierten el certificado de firma de una app en un hash?
Para convertir los certificados de firma en un hash antes de agregarlos a CarrierConfig.xml
, haz lo siguiente:
- Convierte la firma del certificado de firma en un array de bytes con
toByteArray
. - Usa
MessageDigest
para convertir el array de bytes en un hash en el tipo byte[]. -
Convierte el hash de byte[] en un formato de cadena hexadecimal. Para ver un ejemplo, consulta
IccUtils.java
.List<String> certHashes = new ArrayList<>(); PackageInfo pInfo; // Carrier app PackageInfo MessageDigest md = MessageDigest.getInstance("SHA-256"); for (Signature signature : pInfo.signatures) { certHashes.add(bytesToHexString(md.digest(signature.toByteArray())); }
Si
certHashes
es un array de tamaño2
con un valor de12345
y54321
, agrega lo siguiente al archivo de configuración del operador.<string-array name="carrier_certificate_string_array" num="2"> <item value="12345"/> <item value="54321"/> </string-array>