Skip to content

Most visited

Recently visited

navigation

Atestación de claves

La atestación de claves te brinda más confianza respecto del hecho de que las claves que usas en tu app se almacenan en el depósito de claves guardado en hardware del dispositivo. En las siguientes secciones se describe la manera de verificar las propiedades de las claves guardadas en hardware e interpretar el esquema de los datos de extensión del certificado de atestación.

Nota: Solo unos pocos dispositivos con Android 7.0 (nivel de API 24) admiten atestación de claves en el nivel del hardware; en todos los demás dispositivos con Android 7.0 se usa atestación de claves en el nivel del software. Antes de verificar las propiedades de las claves guardadas en hardware de un dispositivo en un entorno de producción, debes asegurarte de que el dispositivo admita atestación de claves en el nivel del hardware. Para esto, debes comprobar que la cadena del certificado de atestación contenga un certificado raíz firmado por la clave raíz de atestación de Google y que el elemento attestationSecurityLevel dentro de la estructura de datos de la descripción de la clave se configure en el nivel de seguridad TrustedEnvironment.

Recuperación y verificación de un par de claves guardado en hardware

Durante la atestación de claves, debes especificar el alias de un par de claves. La herramienta de atestación, como contraprestación, proporciona una cadena de certificados que puedes usar para verificar las propiedades de ese par de claves.

Si el dispositivo admite atestación de claves en el nivel del hardware, el certificado raíz de esa cadena se firma usando una clave raíz de atestación, que el fabricante del dispositivo incluye en el depósito de claves guardadas en hardware del dispositivo en la fábrica.

Nota: En dispositivos que cuentan con atestación de claves guardadas en hardware, Android 7.0 (nivel de API 24) y Google Play Services, el certificado raíz se firma mediante la clave raíz de atestación de Google. Debes verificar que este certificado raíz aparezca en la lista de certificados raíz de Google.

Para implementar la atestación de claves, realiza lo siguiente:

  1. Usa el método getCertificateChain() de un objeto KeyStore para obtener una referencia a la cadena de certificados X.509 asociada con el depósito de claves guardadas en hardware.
  2. Comprueba la validez de cada certificado usando el método isRevoked() de un objeto CRL.

    Advertencia: Si bien puedes completar este proceso directamente en la app, es más seguro comprobar las listas de revocación de los certificados en otro servidor en el que confíes.

  3. Crea un objeto Attestation pasando el primer elemento de la cadena de certificados como un argumento:

    // "certificates" contains the certificate chain associated with a specific key
    // pair in the device's hardware-backed keystore.
    X509Certificate attestationCert = (X509Certificate) certificates[0];
    Attestation hardwareKeyAttestation = new Attestation(attestationCert);
    

    Un objeto de atestación extrae los datos de extensión del certificado y almacena esa información en un formato más accesible. Para obtener más información sobre el esquema de los datos de extensión, consulta Esquema de los datos de extensión de los certificados.

  4. Usa los métodos de descriptores de acceso de la clase Attestation para recuperar los datos de extensión del certificado. Estos métodos usan los mismos nombres y la misma jerarquía de estructura que el esquema de datos de extensión del certificado.

    Por ejemplo, para ver la clave de inicio verificada para el TEE del dispositivo, usa la siguiente secuencia de métodos:

    // "hardwareKeyAttestation" contains the first element of the attestation
    // certificate chain.
    AuthorizationList teeAuthList = hardwareKeyAttestation.getTeeEnforced();
    RootOfTrust teeRootOfTrust = teeAuthList.getRootOfTrust();
    byte[] teeVerifiedBootKey = teeRootOfTrust.getVerifiedBootKey();
    
  5. Compara los datos de extensión del objeto Attestation con el conjunto de valores que esperas que contenga la clave guardada en hardware.

    Advertencia: Si bien puedes completar este proceso directamente en la app, es más seguro comprobar los datos de extensión del certificado en otro servidor en el que confíes.

Esquema de los datos de extensión de los certificados

La atestación de claves verifica los datos de extensión que aparecen en el primer certificado de la cadena en un depósito de claves guardadas en hardware de un dispositivo. El certificado almacena la información de acuerdo con el siguiente esquema ASN.1:

KeyDescription ::= SEQUENCE {
    attestationVersion  INTEGER,
    attestationSecurityLevel  SecurityLevel,
    keymasterVersion  INTEGER,
    keymasterSecurityLevel  SecurityLevel,
    attestationChallenge  OCTET_STRING,
    reserved  OCTET_STRING,
    softwareEnforced  AuthorizationList,
    teeEnforced  AuthorizationList,
}

SecurityLevel ::= ENUMERATED {
    Software  (0),
    TrustedEnvironment  (1),
}

AuthorizationList ::= SEQUENCE {
    purpose  [1] EXPLICIT SET OF INTEGER OPTIONAL,
    algorithm  [2] EXPLICIT INTEGER OPTIONAL,
    keySize  [3] EXPLICIT INTEGER OPTIONAL,
    digest  [5] EXPLICIT SET OF INTEGER OPTIONAL,
    padding  [6] EXPLICIT SET OF INTEGER OPTIONAL,
    ecCurve  [10] EXPLICIT INTEGER OPTIONAL,
    rsaPublicExponent  [200] EXPLICIT INTEGER OPTIONAL,
    activeDateTime  [400] EXPLICIT INTEGER OPTIONAL,
    originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
    usageExpireDateTime  [402] EXPLICIT INTEGER OPTIONAL,
    noAuthRequired  [503] EXPLICIT NULL OPTIONAL,
    userAuthType  [504] EXPLICIT INTEGER OPTIONAL,
    authTimeout  [505] EXPLICIT INTEGER OPTIONAL,
    allowWhileOnBody  [506] EXPLICIT NULL OPTIONAL,
    allApplications  [600] EXPLICIT NULL OPTIONAL,
    applicationId  [601] EXPLICIT OCTET_STRING OPTIONAL,
    creationDateTime  [701] EXPLICIT INTEGER OPTIONAL,
    origin  [702] EXPLICIT INTEGER OPTIONAL,
    rollbackResistant  [703] EXPLICIT NULL OPTIONAL,
    rootOfTrust  [704] EXPLICIT RootOfTrust OPTIONAL,
    osVersion  [705] EXPLICIT INTEGER OPTIONAL,
    osPatchLevel  [706] EXPLICIT INTEGER OPTIONAL,
    attestationChallenge  [708] EXPLICIT INTEGER OPTIONAL,
    attestationApplicationId  [709] EXPLICIT OCTET_STRING OPTIONAL,
}

RootOfTrust ::= SEQUENCE {
    verifiedBootKey  OCTET_STRING,
    deviceLocked  BOOLEAN,
    verifiedBootState  VerifiedBootState,
}

VerifiedBootState ::= ENUMERATED {
    Verified  (0),
    SelfSigned  (1),
    Unverified  (2),
    Failed  (3),
}

En la lista siguiente se proporciona una descripción de cada elemento del esquema:

KeyDescription

Esta secuencia de valores ofrece información general sobre el par de claves que se verifica mediante la atestación de claves, y proporciona acceso sencillo a detalles adicionales.

attestationVersion
Versión de la función de atestación de claves. Debe fijarse en 1.
attestationSecurityLevel

Nivel de seguridad de la atestación.

Advertencia: Si bien es posible atestar claves almacenadas en el sistema Android (es decir, si el valor de attestationSecurityLevel se fija en Software), no puedes confiar en esas atestaciones si el sistema Android se ve comprometido.

keymasterVersion
Versión de la capa de abstracción de hardware (HAL) de Keymaster. Usa 0 para representar la versión 0.2 o 0.3, 1 para representar la versión 1.0 y 2 para representar la versión 2.0.
keymasterSecurityLevel
Nivel de seguridad de la implementación de Keymaster.
attestationChallenge
String de comprobación asociada con un par de claves verificado mediante atestación de claves.
reserved
Solo las apps del sistema usan este valor. En todas las demás apps, este valor está vacío.
softwareEnforced
Opcional. Es la lista de autorización de Keymaster que aplica el sistema Android, no el TEE del dispositivo.
teeEnforced
Opcional. Es la lista de autorización de Keymaster que aplica el TEE del dispositivo.

SecurityLevel

Esta estructura de datos indica el nivel de protección de una función de software, como un par de claves, en función de su ubicación en el dispositivo.

Dado que la estructura de datos es una enumeración, adquiere exactamente uno de los siguientes valores:

Software
La lógica para crear y controlar la función se implementa en el sistema Android. Para la creación y el almacenamiento de pares de claves, esta ubicación es menos segura que el TEE, pero es más segura que el espacio de procesos de tu app.
TrustedEnvironment
La lógica para crear y controlar la función se implementa en hardware seguro, como un TEE. Para la creación y el almacenamiento de pares de claves, esta ubicación es más segura porque el hardware seguro es muy resistente a los peligros remotos.

AuthorizationList

Esta estructura de datos contiene las propiedades del par de claves, como se define en la capa de abstracción de hardware (HAL) de Keymaster. Debes comparar estos valores con el estado actual del dispositivo o con un conjunto de valores previstos para verificar que un par de claves siga siendo válido para usarse en tu app.

Cada nombre de campo corresponde a una etiqueta de Keymaster con una denominación similar. Por ejemplo, el campo keySize en una lista de autorizaciones corresponde a la etiqueta KM_TAG_KEY_SIZE de Keymaster.

Cada uno de los campos de la siguiente lista es opcional:

purpose
Corresponde a la etiqueta KM_TAG_PURPOSE de Keymaster, que usa un valor de ID de etiqueta de 1.
algorithm

Corresponde a la etiqueta KM_TAG_ALGORITHM de Keymaster, que usa un valor de ID de etiqueta de 2.

Cuando un objeto AuthorizationList se asocia con la atestación de claves, este valor es siempre KM_ALGORITHM_RSA o KM_ALGORITHM_EC.

keySize
Corresponde a la etiqueta KM_TAG_KEY_SIZE de Keymaster, que usa un valor de ID de etiqueta de 3.
digest
Corresponde a la etiqueta KM_TAG_DIGEST de Keymaster, que usa un valor de ID de etiqueta de 5.
padding
Corresponde a la etiqueta KM_TAG_PADDING de Keymaster, que usa un valor de ID de etiqueta de 6.
ecCurve

Corresponde a la etiqueta KM_TAG_EC_CURVE de Keymaster, que usa un valor de ID de etiqueta de 10.

Es el conjunto de parámetros empleados para generar un par de claves de curva elíptica (CE), que usa ECDSA para la firma y verificación, en el depósito de claves del sistema Android.

rsaPublicExponent
Corresponde a la etiqueta KM_TAG_RSA_PUBLIC_EXPONENT de Keymaster, que usa un valor de ID de etiqueta de 200.
activeDateTime
Corresponde a la etiqueta KM_TAG_ACTIVE_DATETIME de Keymaster, que usa un valor de ID de etiqueta de 400.
originationExpireDateTime
Corresponde a la etiqueta KM_TAG_ORIGINATION_EXPIRE_DATETIME de Keymaster, que usa un valor de ID de etiqueta de 401.
usageExpireDateTime
Corresponde a la etiqueta KM_TAG_USAGE_EXPIRE_DATETIME de Keymaster, que usa un valor de ID de etiqueta de 402.
noAuthRequired

Corresponde a la etiqueta KM_TAG_NO_AUTH_REQUIRED de Keymaster, que usa un valor de ID de etiqueta de 503.

Cuando un objeto AuthorizationList se asocia con la atestación de claves, este valor es siempre true.

userAuthType
Corresponde a la etiqueta KM_TAG_USER_AUTH_TYPE de Keymaster, que usa un valor de ID de etiqueta de 504.
authTimeout
Corresponde a la etiqueta KM_TAG_AUTH_TIMEOUT de Keymaster, que usa un valor de ID de etiqueta de 505.
allowWhileOnBody

Corresponde a la etiqueta KM_TAG_ALLOW_WHILE_ON_BODY de Keymaster, que usa un valor de ID de etiqueta de 506.

Permite usar la clave después de su período de espera para la autenticación, si el usuario todavía lleva el dispositivo consigo. Recuerda que un sensor seguro de contacto con el cuerpo determina si el dispositivo está en contacto con el cuerpo del usuario.

Cuando un objeto AuthorizationList se asocia con la atestación de claves, este valor es siempre true.

allApplications

Corresponde a la etiqueta KM_TAG_ALL_APPLICATIONS de Keymaster, que usa un valor de ID de etiqueta de 600.

Indica si todas las apps de un dispositivo pueden acceder al par de claves.

Cuando un objeto AuthorizationList se asocia con la atestación de claves, este valor es siempre true.

applicationId
Corresponde a la etiqueta KM_TAG_APPLICATION_ID de Keymaster, que usa un valor de ID de etiqueta de 601.
creationDateTime
Corresponde a la etiqueta KM_TAG_CREATION_DATETIME de Keymaster, que usa un valor de ID de etiqueta de 701.
origin

Corresponde a la etiqueta KM_TAG_ORIGIN de Keymaster, que usa un valor de ID de etiqueta de 702.

Cuando un objeto AuthorizationList se asocia con la atestación de claves, este valor generalmente se fija en KM_ORIGIN_GENERATED. No obstante, si la atestación usa la versión 0.2 o 0.3 de Keymaster, el origen puede fijarse en KM_ORIGIN_UNKNOWN.

rollbackResistant
Corresponde a la etiqueta KM_TAG_ROLLBACK_RESISTANT de Keymaster, que usa un valor de ID de etiqueta de 703.
rootOfTrust

Corresponde a la etiqueta KM_TAG_ROOT_OF_TRUST de Keymaster, que usa un valor de ID de etiqueta de 704.

Para obtener más información, consulta la sección en la que se describe la estructura de datos de RootOfTrust.

osVersion

Corresponde a la etiqueta KM_TAG_OS_VERSION de Keymaster, que usa un valor de ID de etiqueta de 705.

Es la versión del sistema operativo Android asociada con Keymaster, especificada como un número entero de seis dígitos. Por ejemplo, la versión 6.0.1 se representa como 060001.

Solo en la versión 1.0 o las versiones posteriores de Keymaster se incluye este valor en la lista de autorizaciones.

osPatchLevel

Corresponde a la etiqueta KM_TAG_PATCHLEVEL de Keymaster, que usa un valor de ID de etiqueta de 706.

El mes y año asociados con el parche de seguridad que se usa en Keymaster, especificados como un número entero de seis dígitos. Por ejemplo, el parche junio 2016 se representa como 201606.

Solo en la versión 1.0 o las versiones posteriores de Keymaster se incluye este valor en la lista de autorizaciones.

attestationChallenge

Corresponde a la etiqueta KM_TAG_ATTESTATION_CHALLENGE de Keymaster, que usa un valor de ID de etiqueta de 708.

Es la string de comprobación asociada con el par de claves que se define en Keymaster.

attestationApplicationId

Corresponde a la etiqueta KM_TAG_ATTESTATION_APPLICATION_ID de Keymaster, que usa un valor de ID de etiqueta de 709.

Es el ID exclusivo del certificado de atestación que firmó el par de claves que se encuentra en Keymaster.

RootOfTrust

Este conjunto de valores definen información clave sobre el estado del dispositivo.

Cada uno de los campos de la siguiente lista es obligatorio:

verifiedBootKey

Un hash seguro de la clave que verifica la imagen del sistema. Se recomienda que uses el algoritmo SHA-256 para este hash.

deviceLocked
Se presenta cuando el bootloader del dispositivo está bloqueado, lo cual habilita la comprobación de Verified Boot y evita que se transmita al dispositivo una imagen del dispositivo sin firmar. Para obtener más información sobre esta función, consulta la documentación de verificación del inicio.
verifiedBootState
Estado de inicio del dispositivo, según la función Verified Boot.
osVersion
Versión actual del sistema operativo Android del dispositivo, especificado con un número entero de seis dígitos. Por ejemplo, la versión 6.0.1 se representa como 060001.
patchMonthYear
El mes y el año asociados con el parche de seguridad actualmente instalado en el dispositivo, especificados como un número entero de seis dígitos. Por ejemplo, el parche agosto 2016 se representa como 201608.

VerifiedBootState

Esta estructura de datos proporciona el estado de inicio actual del dispositivo, que representa el nivel de protección proporcionado al usuario y a las apps una vez que el dispositivo termina de iniciarse. Para obtener más información sobre esta función, consulta la sección Boot State en la documentación de verificación del inicio.

Esta estructura de datos es una enumeración, por lo cual adquiere exactamente uno de los siguientes valores:

Verified

Indica una cadena completa de confianza, que incluye el bootloader, la partición de inicio y todas las particiones verificadas.

Cuando el dispositivo se encuentra en este estado de inicio, verifiedBootKey es el hash del certificado integrado en el dispositivo, que el fabricante de este último agrega a la ROM del dispositivo en la fábrica.

SelfSigned

Indica que el certificado integrado en el dispositivo verificó la partición de inicio del dispositivo y que la firma es válida.

Cuando el dispositivo se encuentra en este estado de inicio, verifiedBootKey es el hash de un certificado instalado por el usuario, que firma una partición de inicio que el usuario agrega al dispositivo en lugar de la partición de inicio original proporcionada por el fabricante.

Unverified
Indica que el usuario puede modificar el dispositivo libremente. Por lo tanto, el usuario es responsable de verificar la integridad del dispositivo.
Failed
Indica que el dispositivo no superó la verificación. El certificado de atestación nunca debe usar este valor para VerifiedBootState.
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)