Dans Keymaster 1, toutes les clés Keymaster étaient liées de manière cryptographique à la racine de confiance de l'appareil, ou à la clé de démarrage validé. Dans Keymaster 2 et 3, toutes les clés sont également liées au système d'exploitation et au niveau de correctif de l'image système. Cela permet de s'assurer qu'un pirate informatique qui découvre une faille dans une ancienne version du logiciel système ou TEE ne peut pas rétablir la version vulnérable sur un appareil et utiliser les clés créées avec la version plus récente. De plus, lorsqu'une clé avec une version et un niveau de correctif donnés est utilisée sur un appareil qui a été mis à niveau vers une version ou un niveau de correctif plus récents, la clé est mise à niveau avant de pouvoir être utilisée, et la version précédente de la clé est invalidée. Ainsi, à mesure que l'appareil est mis à niveau, les clés "avancent" avec l'appareil, mais toute restauration de l'appareil à une version antérieure rend les clés inutilisables.
Pour prendre en charge la structure modulaire de Treble et rompre la liaison entre system.img et boot.img, Keymaster 4 a modifié le modèle de liaison de la version de clé afin d'avoir des niveaux de correctifs distincts pour chaque partition. Cela permet de mettre à jour chaque partition indépendamment, tout en offrant une protection contre le rollback.
Pour implémenter cette liaison de version, l'application de confiance (TA) KeyMint a besoin d'un moyen de recevoir de manière sécurisée la version actuelle de l'OS et les niveaux de correctifs, et de s'assurer que les informations qu'elle reçoit correspondent à toutes les informations sur le système en cours d'exécution.
- Les appareils équipés d'Android Verified Boot (AVB) peuvent placer tous les niveaux de correctifs et la version du système dans vbmeta, afin que le bootloader puisse les fournir à Keymaster. Pour les partitions chaînées, les informations sur la version de la partition se trouvent dans le fichier vbmeta chaîné. En général, les informations sur la version doivent figurer dans le
vbmeta struct
qui contient les données de validation (hachage ou arbre de hachage) pour une partition donnée. - Sur les appareils sans AVB :
- Les implémentations de Verified Boot doivent fournir un hachage des métadonnées de version au bootloader, afin que le bootloader puisse fournir le hachage à Keymaster.
boot.img
peut continuer à stocker le niveau de correctif dans l'en-tête.system.img
peut continuer à stocker le niveau de correctif et la version de l'OS dans des propriétés en lecture seule.vendor.img
stocke le niveau de correctif dans la propriété en lecture seulero.vendor.build.version.security_patch
.- Le bootloader peut fournir un hachage de toutes les données validées par le démarrage validé à Keymaster.
- Dans Android 9, utilisez les tags suivants pour fournir des informations sur la version des partitions suivantes :
VENDOR_PATCH_LEVEL
: partitionvendor
BOOT_PATCH_LEVEL
: partitionboot
OS_PATCH_LEVEL
etOS_VERSION
: partitionsystem
. (OS_VERSION
est supprimé de l'en-têteboot.img
.
-
Les implémentations Keymaster doivent traiter tous les niveaux de correctifs de manière indépendante. Les clés sont utilisables si toutes les informations sur la version correspondent aux valeurs associées à une clé et que
IKeymaster::upgradeDevice()
passe à un niveau de correctif supérieur si nécessaire.
Modifications apportées à HAL
Pour prendre en charge l'association et l'attestation de version, Android 7.1 a ajouté les tags Tag::OS_VERSION
et Tag::OS_PATCHLEVEL
, ainsi que les méthodes configure
et upgradeKey
. Les tags de version sont automatiquement ajoutés par les implémentations Keymaster 2+ à toutes les clés nouvellement générées (ou mises à jour). De plus, toute tentative d'utilisation d'une clé dont la version de l'OS ou le niveau de correctif ne correspondent pas à la version ou au niveau de correctif actuels du système d'exploitation est rejetée avec le code d'erreur ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
est une valeur UINT
qui représente les parties majeure, mineure et de correction d'une version du système Android au format MMmmss, où MM correspond à la version majeure, mm à la version mineure et ss à la version de correction. Par exemple, la version 6.1.2 est représentée par 060102.
Tag::OS_PATCHLEVEL
est une valeur UINT
qui représente l'année et le mois de la dernière mise à jour du système au format AAAAMM, où AAAA correspond à l'année à quatre chiffres et MM au mois à deux chiffres. Par exemple, mars 2016 serait représenté par 201603.
UpgradeKey
Pour permettre la mise à niveau des clés vers la nouvelle version de l'OS et le nouveau niveau de correctif de l'image système, Android 7.1 a ajouté la méthode upgradeKey
au 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
est la structure de l'appareilkeyBlobToUpgrade
est la clé à mettre à niveau.upgradeParams
sont les paramètres nécessaires pour mettre à niveau la clé. Il s'agit deTag::APPLICATION_ID
etTag::APPLICATION_DATA
, qui sont nécessaires pour déchiffrer le blob de clé, s'ils ont été fournis lors de la génération.upgradedKeyBlob
est le paramètre de sortie utilisé pour renvoyer le nouvel objet blob de clé.
Si upgradeKey
est appelé avec un blob de clé qui ne peut pas être analysé ou qui n'est pas valide, il renvoie ErrorCode::INVALID_KEY_BLOB
. S'il est appelé avec une clé dont le niveau de correctif est supérieur à la valeur système actuelle, il renvoie ErrorCode::INVALID_ARGUMENT
. Si elle est appelée avec une clé dont la version de l'OS est supérieure à la valeur système actuelle et que la valeur système est différente de zéro, elle renvoie ErrorCode::INVALID_ARGUMENT
. Les mises à niveau de version d'OS de non-zéro à zéro sont autorisées. En cas d'erreur de communication avec le monde sécurisé, il renvoie une valeur d'erreur appropriée (par exemple, ErrorCode::SECURE_HW_ACCESS_DENIED
, ErrorCode::SECURE_HW_BUSY
). Sinon, il renvoie ErrorCode::OK
et renvoie un nouveau blob de clé dans upgradedKeyBlob
.
keyBlobToUpgrade
reste valide après l'appel upgradeKey
et pourrait théoriquement être réutilisé si l'appareil était rétrogradé. En pratique, le keystore appelle généralement deleteKey
sur le blob keyBlobToUpgrade
peu de temps après l'appel à upgradeKey
. Si keyBlobToUpgrade
avait le tag Tag::ROLLBACK_RESISTANT
, upgradedKeyBlob
devrait également l'avoir (et devrait être résistant aux rollbacks).
Configuration sécurisée
Pour implémenter la liaison de version, la TA Keymaster a besoin d'un moyen de recevoir de manière sécurisée la version actuelle de l'OS et le niveau de correctif (informations sur la version), et de s'assurer que les informations qu'elle reçoit correspondent fortement à celles du système en cours d'exécution.
Pour permettre la transmission sécurisée des informations sur la version au TA, un champ OS_VERSION
a été ajouté à l'en-tête de l'image de démarrage. Le script de compilation de l'image de démarrage renseigne automatiquement ce champ. Les OEM et les implémenteurs de TA Keymaster doivent collaborer pour modifier les bootloaders des appareils afin d'extraire les informations sur la version de l'image de démarrage et de les transmettre à la TA avant le démarrage du système non sécurisé. Cela permet de s'assurer que les pirates informatiques ne peuvent pas interférer avec le provisionnement des informations sur la version au TA.
Il est également nécessaire de s'assurer que l'image système contient les mêmes informations de version que l'image de démarrage. Pour ce faire, la méthode "configure" a été ajoutée à la HAL Keymaster :
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
L'argument params
contient Tag::OS_VERSION
et Tag::OS_PATCHLEVEL
. Cette méthode est appelée par les clients keymaster2 après l'ouverture du HAL, mais avant l'appel de toute autre méthode. Si une autre méthode est appelée avant la configuration, le TA renvoie ErrorCode::KEYMASTER_NOT_CONFIGURED
.
La première fois que configure
est appelé après le démarrage de l'appareil, il doit vérifier que les informations de version fournies correspondent à celles fournies par le bootloader. Si les informations sur la version ne correspondent pas, configure
renvoie ErrorCode::INVALID_ARGUMENT
, et toutes les autres méthodes Keymaster continuent de renvoyer ErrorCode::KEYMASTER_NOT_CONFIGURED
. Si les informations correspondent, configure
renvoie ErrorCode::OK
et les autres méthodes Keymaster commencent à fonctionner normalement.
Les appels suivants à configure
renvoient la même valeur que le premier appel et ne modifient pas l'état de Keymaster.
Étant donné que configure
est appelé par le système dont il est censé valider le contenu, un pirate informatique dispose d'une fenêtre d'opportunité étroite pour compromettre l'image système et la forcer à fournir des informations sur la version qui correspondent à l'image de démarrage, mais qui ne correspondent pas à la version réelle du système. La combinaison de la validation de l'image de démarrage, de la validation dm-verity du contenu de l'image système et du fait que configure
est appelé très tôt au démarrage du système devrait rendre cette opportunité difficile à exploiter.