Vinculación de versión

En Keymaster 1, todas las claves maestras de claves estaban vinculadas de manera criptográfica al dispositivo. Raíz de confianza o clave de inicio verificado. En Keymaster 2 y 3, todas también están vinculadas al sistema operativo y al nivel de parche de la imagen del sistema. Esto asegura que un atacante que descubra una debilidad en un versión del sistema o software de TEE no puede revertir un dispositivo al estado y usar claves creadas con la versión más reciente. Además, cuando una clave con una versión y un nivel de parche determinados se usan en un dispositivo que se actualizó a una versión o un nivel de parche más nuevos, la clave se actualiza antes de que se pueda usar y se invalidó la versión anterior de la clave. De esta manera, actualizadas, las claves “trinquete” hacia adelante junto con el dispositivo, pero cualquier revertir el dispositivo a una versión anterior hará que las claves se inutilizable.

Para admitir la estructura modular de Treble y romper la vinculación de system.img en boot.img, Keymaster 4 cambió el modelo de vinculación de versión de clave para que tuviera los niveles de parche de cada partición. Esto permite actualizar cada partición de forma independiente, sin dejar de ofrecer protección contra reversiones.

En Android 9, se pueden usar boot, system y vendor. cada una de ellas tiene su propio nivel de parche.

  • Los dispositivos con inicio verificado de Android (AVB) pueden incluir todos los niveles de parche y la versión del sistema en vbmeta, para que el bootloader pueda proporcionarlos Keymaster Para particiones en cadena, la información de la versión de la partición estar en el encadenado vbmeta. En general, la información de la versión debe estar en vbmeta struct que contiene los datos de verificación (hash o hashtree) para una partición determinada.
  • En dispositivos sin AVB:
    • Las implementaciones de inicio verificado deben proporcionar un hash de la versión metadatos al bootloader, de modo que el bootloader pueda proporcionar el hash a Keymaster.
    • boot.img puede seguir almacenando el nivel del parche en el encabezado.
    • system.img puede seguir almacenando el nivel de parche y la versión del SO en modo de solo lectura. propiedades
    • vendor.img almacena el nivel de parche en la propiedad de solo lectura. ro.vendor.build.version.security_patch
    • El bootloader puede proporcionar un hash de todos los datos validados por el inicio verificado a keymaster.
  • En Android 9, usa las siguientes etiquetas para proporcionar información de la versión para las siguientes particiones:
    • VENDOR_PATCH_LEVEL: partición vendor
    • BOOT_PATCH_LEVEL: partición boot
    • OS_PATCH_LEVEL y OS_VERSION: system. (OS_VERSION se elimina de el encabezado boot.img.
  • Las implementaciones de Keymaster deben tratar todos los niveles de parches de forma independiente. Las claves son utilizable si toda la información de la versión coincide con los valores asociados con una clave. IKeymaster::upgradeDevice() lanza a un nivel de parche más alto si según tus necesidades.

Cambios en la HAL

Para admitir la vinculación de versión y la certificación de versión, en Android 7.1 se agregó el las etiquetas Tag::OS_VERSION, Tag::OS_PATCHLEVEL y el los métodos configure y upgradeKey. Las etiquetas de la versión se agregan automáticamente mediante las implementaciones de Keymaster 2+ a todas las versiones claves (o actualizadas). Además, cualquier intento de usar una clave que no tenga un SO versión o el nivel de parche que coincidan con la versión actual del SO del sistema o el nivel de parche, respectivamente, se rechaza con ErrorCode::KEY_REQUIRES_UPGRADE.

Tag::OS_VERSION es un valor UINT que representa la principales, menores y submenores de una versión del sistema Android como MMmmss. donde MM es la versión principal, mm es la versión secundaria y ss es la submenor versión. Por ejemplo, 6.1.2 se representaría como 060102.

Tag::OS_PATCHLEVEL es un valor UINT que representa la el año y el mes de la última actualización en el sistema como AAAAMM, donde AAAA es el año de cuatro dígitos y MM es el mes de dos dígitos. Por ejemplo, marzo de 2016 sería representado como 201603.

Clave de actualización

Para permitir que las claves se actualicen a la nueva versión del SO y el nivel de parche del sistema Android 7.1 agregó el método upgradeKey a la HAL:

Keymaster 3

    upgradeKey(vec keyBlobToUpgrade, vec upgradeParams)
        generates(ErrorCode error, vec upgradedKeyBlob);

Keymaster 2

keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev,
    const keymaster_key_blob_t* key_to_upgrade,
    const keymaster_key_param_set_t* upgrade_params,
    keymaster_key_blob_t* upgraded_key);
  • dev es la estructura del dispositivo.
  • La clave que se debe actualizar es keyBlobToUpgrade
  • upgradeParams son parámetros necesarios para actualizar la clave. Estos incluirá Tag::APPLICATION_ID y Tag::APPLICATION_DATA, que son necesarios para desencriptar la clave BLOB, si se proporcionaron durante la generación.
  • upgradedKeyBlob es el parámetro de salida, que se usa para mostrar el nuevo BLOB de clave.

Si se llama a upgradeKey con un BLOB de claves que no se puede analizar o si no es válido, muestra ErrorCode::INVALID_KEY_BLOB. Si se llama con una clave cuyo nivel de parche es mayor que el valor actual del sistema se muestra ErrorCode::INVALID_ARGUMENT. Si se llama con una clave cuya versión del SO sea superior al valor actual del sistema y el valor es distinto de cero, muestra ErrorCode::INVALID_ARGUMENT. Versión del SO se permiten las actualizaciones de cero a cero. En caso de errores cuando se comunica con el mundo seguro, devuelve un valor de error apropiado (p.ej., ErrorCode::SECURE_HW_ACCESS_DENIED, ErrorCode::SECURE_HW_BUSY). De lo contrario, muestra ErrorCode::OK y muestra un nuevo BLOB de clave en upgradedKeyBlob

keyBlobToUpgrade sigue siendo válido después de upgradeKey llamada y, en teoría, podría usarse de nuevo si el dispositivo se cambiara a una versión inferior. En Por lo general, el almacén de claves llama a deleteKey en el BLOB keyBlobToUpgrade poco después de la llamada a upgradeKey Si keyBlobToUpgrade tuviera una etiqueta Tag::ROLLBACK_RESISTANT; luego, upgradedKeyBlob debería y debe ser resistente a las reversiones).

Configuración segura

Para implementar la vinculación de versión, el TA de la instancia principal necesita una forma de recibir la versión actual del SO y el nivel de parche (información de la versión), y garantizar que la información que recibe coincide en gran medida con la información del servidor en un sistema de archivos.

Para admitir la entrega segura de información de la versión al TA, se debe realizar una OS_VERSION campo al encabezado de la imagen de arranque. La compilación de la imagen de arranque secuencia de comandos propaga automáticamente este campo. Implementadores de TA de OEM e implementadores de TA de keymaster necesitan trabajar juntos para modificar los bootloaders del dispositivo y extraer la versión información de la imagen de arranque y la pasa al TA antes de antes de que se inicie el sistema. Esto garantiza que los atacantes no puedan interferir en el aprovisionamiento de la información de la versión al TA.

También es necesario asegurarse de que la imagen del sistema tenga la misma versión información como la imagen de arranque. Para ello, se agregó el método de configuración a la HAL de keymaster:

keymaster_error_t (*configure)(const struct keymaster2_device* dev,
  const keymaster_key_param_set_t* params);

El argumento params contiene Tag::OS_VERSION y Tag::OS_PATCHLEVEL Los clientes keymaster2 llaman a este método. después de abrir la HAL, pero antes de llamar a cualquier otro método. Si se utiliza otro método, se llama antes de la configuración, la TA devuelve ErrorCode::KEYMASTER_NOT_CONFIGURED

La primera vez que se llama a configure después de que se inicia el dispositivo, debemos verificar que la información de la versión proporcionada coincida con la que proporcionó el bootloader. Si la información de la versión no coincide, configure muestra ErrorCode::INVALID_ARGUMENT y todos otros métodos de keymaster continúan mostrando ErrorCode::KEYMASTER_NOT_CONFIGURED Si la información coincide, configure muestra ErrorCode::OK y otro keymaster. los métodos empiezan a funcionar con normalidad.

Las llamadas posteriores a configure muestran el mismo valor que muestra el primera llamada y no cambien el estado de keymaster. Ten en cuenta que este proceso requiere que todas las OTA actualicen las imágenes de inicio y del sistema; no se pueden actualizar por separado para mantener sincronizada la información de la versión.

Porque el sistema cuyo contenido llamará a configure la validación, existe una pequeña ventana de oportunidad para que un atacante comprometer la imagen del sistema y forzarla a proporcionar información de la versión que coincide con la imagen de arranque, pero que no es la versión real del sistema. El combinación de verificación de imagen de inicio, validación de dm-verity de la imagen del sistema de contenido, y el hecho de que se llame a configure al principio de la el inicio del sistema debería dificultar el aprovechamiento de esta ventana de oportunidades.