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. propiedadesvendor.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ónvendor
BOOT_PATCH_LEVEL
: particiónboot
OS_PATCH_LEVEL
yOS_VERSION
:system
. (OS_VERSION
se elimina de el encabezadoboot.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
yTag::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.