Funciones de KeyMint

En esta página, se proporcionan detalles y lineamientos adicionales para ayudar a los implementadores de la capa de abstracción de hardware (HAL) de KeyMint. La documentación principal del HAL es la especificación de la interfaz AIDL.

Uso inadecuado de la API

Los llamadores pueden crear claves de KeyMint con autorizaciones que son válidas como parámetros de API, pero que hacen que las claves resultantes no sean seguras o no se puedan usar. Las implementaciones de KeyMint no son obligatorias para fallar en esos casos ni emitir un diagnóstico. Las implementaciones no deben diagnosticar el uso de claves demasiado pequeñas, la especificación de parámetros de entrada irrelevantes, la reutilización de IVs o nonces, la generación de claves sin ningún propósito (por lo tanto, inútiles) y similares.

Es responsabilidad de las apps, el framework y Android Keystore garantizar que las llamadas a los módulos de KeyMint sean razonables y útiles.

Punto de entrada de addRngEntropy

El punto de entrada addRngEntropy agrega la entropía proporcionada por el llamador al grupo que usa la implementación de KeyMint para generar números aleatorios, para claves y IVs.

Las implementaciones de KeyMint deben combinar de forma segura la entropía proporcionada en su grupo, que también debe contener entropía generada internamente a partir de un generador de números aleatorios de hardware. La combinación debe controlarse de modo que un atacante que tenga el control completo de los bits proporcionados por addRngEntropy o los bits generados por el hardware (pero no ambos) no tenga una ventaja significativa para predecir los bits generados desde el grupo de entropía.

Características clave

Cada uno de los mecanismos (generateKey, importKey y importWrappedKey) que crean claves de KeyMint muestra las características de la clave recién creada, divididas de forma adecuada en los niveles de seguridad que aplican cada característica. Las características que se muestran incluyen todos los parámetros especificados para la creación de claves, excepto Tag::APPLICATION_ID y Tag::APPLICATION_DATA. Si se incluyen estas etiquetas en los parámetros de clave, se quitan de las características que se muestran para que no sea posible encontrar sus valores examinando el keyblob que se muestra. Sin embargo, están vinculados criptográficamente al keyblob, de modo que, si no se proporcionan los valores correctos cuando se usa la clave, el uso falla. Del mismo modo, Tag::ROOT_OF_TRUST está vinculado criptográficamente a la clave, pero no se puede especificar durante la creación o importación de la clave y nunca se muestra.

Además de las etiquetas proporcionadas, la implementación de KeyMint también agrega Tag::ORIGIN, que indica la forma en que se creó la clave (KeyOrigin::GENERATED, KeyOrigin::IMPORTED o KeyOrigin::SECURELY_IMPORTED).

Resistencia a la reversión

Tag::ROLLBACK_RESISTANCE indica la resistencia a la reversión y significa que, una vez que se borra una clave con deleteKey o deleteAllKeys, el hardware seguro garantiza que nunca se pueda volver a usar.

Las implementaciones de KeyMint devuelven material de clave generado o importado al llamador como un keyblob, un formulario encriptado y autenticado. Cuando Keystore borra el keyblob, la clave desaparece, pero un atacante que anteriormente haya logrado recuperar el material de la clave podría restablecerla en el dispositivo.

Una clave es resistente a la reversión si el hardware seguro garantiza que las claves borradas no se puedan restablecer más adelante. Por lo general, esto se hace almacenando metadatos de claves adicionales en una ubicación de confianza que un atacante no pueda manipular. En los dispositivos móviles, el mecanismo que se usa para esto suele ser los bloques de memoria protegidos contra la repetición (RPMB). Debido a que la cantidad de claves que se pueden crear es, en esencia, ilimitada y el almacenamiento de confianza que se usa para la resistencia a la reversión puede ser limitado en tamaño, la implementación puede fallar en las solicitudes para crear claves resistentes a la reversión cuando el almacenamiento está lleno.

begin

El punto de entrada begin() inicia una operación criptográfica con la clave especificada, para el propósito especificado, con los parámetros especificados (según corresponda). Devuelve un nuevo objeto Binder IKeyMintOperation que se usa para completar la operación. Además, se muestra un valor de desafío que se usa como parte del token de autenticación en las operaciones autenticadas.

Una implementación de KeyMint admite al menos 16 operaciones simultáneas. El almacén de claves usa hasta 15, lo que deja uno para que vold use en la encriptación de contraseñas. Cuando Keystore tiene 15 operaciones en curso (se llamó a begin(), pero no a finish ni a abort) y recibe una solicitud para comenzar una 16ª, llama a abort() en la operación que se usó menos recientemente para reducir la cantidad de operaciones activas a 14 antes de llamar a begin() para iniciar la operación solicitada recientemente.

Si se especificaron Tag::APPLICATION_ID o Tag::APPLICATION_DATA durante la generación o importación de claves, las llamadas a begin() deben incluir esas etiquetas con los valores especificados originalmente en el argumento params de este método.

Manejo de errores

Si un método en un IKeyMintOperation muestra un código de error que no es ErrorCode::OK, se aborta la operación y se invalida el objeto Binder de la operación. Cualquier uso futuro del objeto muestra ErrorCode::INVALID_OPERATION_HANDLE.

Aplicación forzosa de la autorización

La aplicación forzosa de la autorización de claves se realiza principalmente en begin(). La única excepción es el caso en el que la clave tiene uno o más valores Tag::USER_SECURE_ID y no tiene un valor Tag::AUTH_TIMEOUT.

En este caso, la clave requiere una autorización por operación, y los métodos update() o finish() reciben un token de autenticación en el argumento authToken. Para garantizar que el token sea válido, la implementación de KeyMint hace lo siguiente:

  • Verifica la firma HMAC en el token de autenticación.
  • Verifica que el token contenga un ID de usuario seguro que coincida con uno asociado con la clave.
  • Verifica que el tipo de autenticación del token coincida con el Tag::USER_AUTH_TYPE de la clave.
  • Verifica que el token contenga el valor del desafío para la operación actual en el campo de desafío.

Si no se cumplen estas condiciones, KeyMint muestra ErrorCode::KEY_USER_NOT_AUTHENTICATED.

El emisor proporciona el token de autenticación a cada llamada a update() y finish(). La implementación solo puede validar el token una vez.