No Keymaster 1, todas as chaves mestras de chaves foram vinculadas criptograficamente ao dispositivo Raiz de confiança ou a chave de inicialização verificada. No Keymaster 2 e 3, todos também são vinculadas ao sistema operacional e ao nível de patch da imagem do sistema. Isso garante que um invasor que descubra uma fraqueza em um sistema do sistema ou o software TEE não revertem um dispositivo para o estado vulnerável e usar as chaves criadas com a versão mais recente. Além disso, quando uma chave com uma determinada versão e nível de patch é usado em um dispositivo que foi atualizado para uma versão mais recente ou nível de patch, a chave é atualizada antes de ser usada, e a versão anterior da chave invalidada. Dessa forma, como o dispositivo atualizadas, as chaves serão "catraca" com o dispositivo, mas qualquer a reversão do dispositivo para uma versão anterior fará com que as chaves sejam inutilizáveis.
Para oferecer suporte à estrutura modular do Treble e romper a vinculação de system.img ao boot.img, o Keymaster 4 alterou o modelo de vinculação de versão da chave para ter os níveis de patch de cada partição. Isso permite atualizar cada partição de forma independente, com proteção contra reversão.
No Android 9, boot
, system
e vendor
cada partição tem o próprio nível de patch.
- Dispositivos com a Inicialização verificada do Android (AVB) podem colocar todos os níveis de patch
e a versão do sistema em vbmeta, de modo que o carregador de inicialização possa fornecê-los ao
o Keymaster: Nas partições encadeadas, as informações da versão da partição
estar na vbmeta encadeada. Em geral, as informações de versão devem estar na
vbmeta struct
que contém os dados de verificação (hash ou hashtree) de uma partição específica. - Em dispositivos sem AVB:
- As implementações de Inicialização verificada precisam fornecer um hash da versão metadados ao carregador de inicialização, para que ele possa fornecer o hash ao Keymaster.
boot.img
pode continuar armazenando o nível do patch no cabeçalhosystem.img
pode continuar armazenando o nível do patch e a versão do SO em modo somente leitura propriedadesvendor.img
armazena o nível do patch na propriedade somente leitura.ro.vendor.build.version.security_patch
.- O carregador de inicialização pode fornecer um hash de todos os dados validados pela inicialização verificada para o keymaster.
- No Android 9, use as seguintes tags para fornecer informações de versão para
as seguintes partições:
VENDOR_PATCH_LEVEL
: partiçãovendor
BOOT_PATCH_LEVEL
: partiçãoboot
OS_PATCH_LEVEL
eOS_VERSION
:system
. (OS_VERSION
foi removido dos no cabeçalhoboot.img
.
-
As implementações do Keymaster devem tratar todos os níveis de patch de forma independente. As chaves são
utilizável se todas as informações de versão corresponderem aos valores associados a uma chave e
IKeymaster::upgradeDevice()
será aplicado a um nível de patch mais alto se necessários.
Mudanças na HAL
Para oferecer suporte à vinculação e ao atestado de versões, o Android 7.1 adicionou a
tags Tag::OS_VERSION
e Tag::OS_PATCHLEVEL
, e as
os métodos configure
e upgradeKey
. As tags de versão
são adicionadas automaticamente pelas implementações do Keymaster 2+ a todas as versões recém-geradas
(ou atualizadas). Além disso, qualquer tentativa de usar uma chave sem um SO
versão ou nível do patch que correspondam à versão atual do SO ou nível do patch,
respectivamente, são rejeitados com ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
é um valor UINT
que representa o
partes principais, secundárias e subsecundárias de uma versão do sistema Android como MMmmss,
em que MM é a versão principal, mm é a versão secundária e ss é a subsecundária.
para a versão anterior. Por exemplo, 6.1.2 seria representado como 060102.
Tag::OS_PATCHLEVEL
é um valor UINT
que representa o
ano e mês da última atualização do sistema como AAAAMM, em que AAAA é o
ano com quatro dígitos e MM é o mês com dois dígitos. Por exemplo, março de 2016 seria
representado como 201603.
UpgradeKey
Permitir o upgrade das chaves para a nova versão do SO e nível do patch do sistema
imagem, o Android 7.1 adicionou o método upgradeKey
à HAL:
Keymaster 3 (link em inglês)
upgradeKey(vec keyBlobToUpgrade, vec upgradeParams) generates(ErrorCode error, vec upgradedKeyBlob);
Keymaster 2 (link em inglês)
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
é a estrutura do dispositivo.keyBlobToUpgrade
é a chave que precisa ser atualizadaupgradeParams
são parâmetros necessários para fazer upgrade da chave. Esses incluiráTag::APPLICATION_ID
eTag::APPLICATION_DATA
, que são necessários para descriptografar a chave caso tenham sido fornecidos durante a geração.upgradedKeyBlob
é o parâmetro de saída, usado para retornar o novo blob de chave.
Se upgradeKey
for chamado com um blob de chave que não pode ser analisado ou
for inválido, ele retornará ErrorCode::INVALID_KEY_BLOB
. Se
é chamado com uma chave cujo nível de patch é maior que o valor atual do sistema,
ela retornará ErrorCode::INVALID_ARGUMENT
. Se for chamado com uma chave
cuja versão do SO é maior que o valor atual do sistema e o valor do sistema
for diferente de zero, ela retornará ErrorCode::INVALID_ARGUMENT
. Versão do SO
são permitidos
upgrades diferentes de zero para zero. Em caso de erros
comunicando-se com o mundo seguro, ele retorna um valor de erro apropriado (por exemplo,
ErrorCode::SECURE_HW_ACCESS_DENIED
,
ErrorCode::SECURE_HW_BUSY
). Caso contrário, retorna
ErrorCode::OK
e retorna um novo blob de chave em
upgradedKeyBlob
.
keyBlobToUpgrade
continua válido após upgradeKey
e teoricamente pode ser usado novamente se o dispositivo sofrer downgrade. Em
prática, o keystore geralmente chama deleteKey
nos
blob keyBlobToUpgrade
logo após a chamada para
upgradeKey
Se keyBlobToUpgrade
tivesse uma tag
Tag::ROLLBACK_RESISTANT
, então upgradedKeyBlob
deverá
ele também precisa ser (e precisa ser resistente a reversões).
Configuração segura
Para implementar a vinculação de versões, o Keymaster TA precisa de uma forma de receber a versão atual do sistema operacional e o nível do patch (informações de versão) e para garantir que as informações recebidas correspondem às informações sobre o sistema.
Para garantir a entrega segura das informações da versão ao TA, um OS_VERSION
foi adicionado ao cabeçalho da imagem de inicialização. O build da imagem de inicialização
script preenche automaticamente esse campo. OEMs e implementadores de keymaster TA
precisam trabalhar em conjunto para modificar os carregadores de inicialização do dispositivo
da imagem de inicialização e passá-la para o TA antes que o dispositivo
sistema é inicializado. Isso garante que os invasores não possam interferir no provisionamento
de informações de versão para o TA.
Também é necessário garantir que a imagem do sistema tenha a mesma versão como a imagem de inicialização. Para isso, o método de configuração foi adicionado para a HAL de keymaster:
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
O argumento params
contém Tag::OS_VERSION
e
Tag::OS_PATCHLEVEL
Esse método é chamado pelos clientes keymaster2
depois de abrir a HAL, mas antes de chamar qualquer outro método. Se outro método
é chamado antes da configuração, o TA retorna
ErrorCode::KEYMASTER_NOT_CONFIGURED
:
Na primeira vez que o método configure
for chamado após a inicialização do dispositivo, ele
deve verificar se as informações da versão fornecidas correspondem às fornecidas pelo
pelo carregador de inicialização. Se as informações da versão não forem iguais,
configure
retorna ErrorCode::INVALID_ARGUMENT
, e todos
outros métodos keymaster continuam retornando
ErrorCode::KEYMASTER_NOT_CONFIGURED
Se as informações forem iguais,
configure
retorna ErrorCode::OK
e outro keymaster
comecem a funcionar normalmente.
Chamadas subsequentes para configure
retornam o mesmo valor retornado pelo
primeira chamada e não altera o estado do keymaster. Esse processo
exige que todas as OTAs atualizem as imagens do sistema e de inicialização; elas não podem ser atualizadas
separadamente para manter as informações da versão sincronizadas.
Como o configure
será chamado pelo sistema cujo conteúdo é
para validar, há uma pequena janela de oportunidade para que um invasor
comprometer a imagem do sistema e forçá-lo a fornecer informações de versão que
corresponde à imagem de inicialização, mas que não é a versão real do sistema. A
combinação de verificação de imagem de inicialização, validação dm-verity da imagem do sistema
conteúdos, e o fato de que configure
é chamado bem no início da
a inicialização do sistema dificulta a exploração dessa janela de oportunidade.