Di Keymaster 1, semua kunci keymaster terikat secara kriptografis ke Root of Trust perangkat, atau kunci Verified Boot. Di Keymaster 2 dan 3, semua kunci juga terikat dengan sistem operasi dan tingkat patch image sistem. Hal ini memastikan bahwa penyerang yang menemukan kelemahan dalam sistem versi lama atau software TEE tidak dapat melakukan roll back perangkat ke versi yang rentan dan menggunakan kunci yang dibuat dengan versi yang lebih baru. Selain itu, saat kunci dengan versi dan level patch tertentu digunakan di perangkat yang telah diupgrade ke versi atau level patch yang lebih baru, kunci akan diupgrade sebelum dapat digunakan, dan versi kunci sebelumnya akan dibatalkan validasinya. Dengan cara ini, saat perangkat diupgrade, tombol akan *ratchet* ke depan bersama dengan perangkat, tetapi reversi perangkat ke rilis sebelumnya akan menyebabkan tombol tidak dapat digunakan.
Untuk mendukung struktur modular Treble dan memisahkan binding system.img ke boot.img, Keymaster 4 mengubah model binding versi kunci agar memiliki tingkat patch terpisah untuk setiap partisi. Hal ini memungkinkan setiap partisi diupdate secara independen, sekaligus tetap memberikan perlindungan rollback.
Di Android 9, partisi boot
, system
, dan vendor
masing-masing memiliki level patch sendiri.
- Perangkat dengan Android Verified Boot (AVB) dapat menempatkan semua level patch
dan versi sistem di vbmeta, sehingga bootloader dapat menyediakannya ke
Keymaster. Untuk partisi berantai, info versi untuk partisi berada
dalam vbmeta berantai. Secara umum, informasi versi harus berada di
vbmeta struct
yang berisi data verifikasi (hash atau hashtree) untuk partisi tertentu. - Di perangkat tanpa AVB:
- Implementasi Verified Boot perlu memberikan hash metadata versi ke bootloader, sehingga bootloader dapat memberikan hash ke Keymaster.
boot.img
dapat terus menyimpan level patch di headersystem.img
dapat terus menyimpan tingkat patch dan versi OS di properti hanya bacavendor.img
menyimpan tingkat patch di properti hanya bacaro.vendor.build.version.security_patch
.- Bootloader dapat memberikan hash dari semua data yang divalidasi oleh booting terverifikasi ke keymaster.
- Di Android 9, gunakan tag berikut untuk memberikan informasi versi untuk
partisi berikut:
VENDOR_PATCH_LEVEL
: Partisivendor
BOOT_PATCH_LEVEL
: Partisiboot
OS_PATCH_LEVEL
danOS_VERSION
: Partisisystem
. (OS_VERSION
dihapus dari headerboot.img
.
-
Implementasi Keymaster harus memperlakukan semua level patch secara terpisah. Kunci dapat
digunakan jika semua info versi cocok dengan nilai yang terkait dengan kunci, dan
IKeymaster::upgradeDevice()
di-roll ke tingkat patch yang lebih tinggi jika diperlukan.
Perubahan HAL
Untuk mendukung binding versi dan pengesahan versi, Android 7.1 menambahkan
tag Tag::OS_VERSION
dan Tag::OS_PATCHLEVEL
serta
metode configure
dan upgradeKey
. Tag versi
otomatis ditambahkan oleh implementasi Keymaster 2+ ke semua kunci yang baru dibuat
(atau diperbarui). Selain itu, setiap upaya untuk menggunakan kunci yang tidak memiliki versi OS
atau tingkat patch yang cocok dengan versi OS sistem atau tingkat patch saat ini,
akan ditolak dengan ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
adalah nilai UINT
yang mewakili
bagian utama, minor, dan sub-minor dari versi sistem Android sebagai MMmmss,
dengan MM adalah versi utama, mm adalah versi minor, dan ss adalah versi sub-minor. Misalnya, 6.1.2 akan direpresentasikan sebagai 060102.
Tag::OS_PATCHLEVEL
adalah nilai UINT
yang mewakili tahun dan bulan update terakhir ke sistem sebagai YYYYMM, dengan YYYY adalah tahun empat digit dan MM adalah bulan dua digit. Misalnya, Maret 2016 akan
diwakili sebagai 201603.
UpgradeKey
Untuk mengizinkan kunci diupgrade ke versi OS baru dan tingkat patch image
sistem, Android 7.1 menambahkan metode upgradeKey
ke 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
adalah struktur perangkatkeyBlobToUpgrade
adalah kunci yang perlu diupgradeupgradeParams
adalah parameter yang diperlukan untuk mengupgrade kunci. Ini mencakupTag::APPLICATION_ID
danTag::APPLICATION_DATA
, yang diperlukan untuk mendekripsi blob kunci, jika disediakan selama pembuatan.upgradedKeyBlob
adalah parameter output, yang digunakan untuk menampilkan blob kunci baru.
Jika upgradeKey
dipanggil dengan blob kunci yang tidak dapat diuraikan atau tidak valid, ErrorCode::INVALID_KEY_BLOB
akan ditampilkan. Jika
dipanggil dengan kunci yang tingkat patch-nya lebih besar dari nilai sistem saat ini,
kunci tersebut akan menampilkan ErrorCode::INVALID_ARGUMENT
. Jika dipanggil dengan kunci
yang versi OS-nya lebih besar dari nilai sistem saat ini, dan nilai sistem
bukan nol, kunci tersebut akan menampilkan ErrorCode::INVALID_ARGUMENT
. Upgrade versi OS
dari bukan nol menjadi nol diizinkan. Jika terjadi error saat berkomunikasi dengan secure world, fungsi ini akan menampilkan nilai error yang sesuai (misalnya,
ErrorCode::SECURE_HW_ACCESS_DENIED
,
ErrorCode::SECURE_HW_BUSY
). Jika tidak, fungsi ini akan menampilkan
ErrorCode::OK
dan menampilkan blob kunci baru di
upgradedKeyBlob
.
keyBlobToUpgrade
tetap valid setelah panggilan
upgradeKey
, dan secara teori dapat digunakan lagi jika perangkat didowngrade. Dalam
praktiknya, keystore umumnya memanggil deleteKey
pada
blob keyBlobToUpgrade
segera setelah panggilan ke
upgradeKey
. Jika keyBlobToUpgrade
memiliki tag
Tag::ROLLBACK_RESISTANT
, upgradedKeyBlob
juga harus
memilikinya (dan harus tahan rollback).
Konfigurasi aman
Untuk menerapkan binding versi, TA keymaster memerlukan cara untuk menerima versi OS dan tingkat patch saat ini (informasi versi) dengan aman, dan untuk memastikan bahwa informasi yang diterima sangat cocok dengan informasi tentang sistem yang sedang berjalan.
Untuk mendukung pengiriman informasi versi yang aman ke TA, kolom
OS_VERSION
telah ditambahkan ke header image booting. Skrip build image booting
akan otomatis mengisi kolom ini. OEM dan implementer TA keymaster
harus bekerja sama untuk memodifikasi bootloader perangkat guna mengekstrak informasi
versi dari image booting dan meneruskannya ke TA sebelum sistem
yang tidak aman di-booting. Hal ini memastikan bahwa penyerang tidak dapat mengganggu penyediaan
informasi versi ke TA.
Anda juga perlu memastikan bahwa image sistem memiliki informasi versi yang sama dengan image booting. Untuk itu, metode konfigurasi telah ditambahkan ke HAL keymaster:
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
Argumen params
berisi Tag::OS_VERSION
dan
Tag::OS_PATCHLEVEL
. Metode ini dipanggil oleh klien keymaster2
setelah membuka HAL, tetapi sebelum memanggil metode lain. Jika metode lain
dipanggil sebelum mengonfigurasi, TA akan menampilkan
ErrorCode::KEYMASTER_NOT_CONFIGURED
.
Saat pertama kali dipanggil setelah perangkat melakukan booting, configure
harus memverifikasi bahwa informasi versi yang diberikan cocok dengan yang diberikan oleh
bootloader. Jika informasi versi tidak cocok,
configure
akan menampilkan ErrorCode::INVALID_ARGUMENT
, dan semua
metode keymaster lainnya akan terus menampilkan
ErrorCode::KEYMASTER_NOT_CONFIGURED
. Jika informasi cocok,
configure
akan menampilkan ErrorCode::OK
, dan metode keymaster
lainnya mulai berfungsi seperti biasa.
Panggilan berikutnya ke configure
menampilkan nilai yang sama dengan yang ditampilkan oleh
panggilan pertama, dan tidak mengubah status keymaster.
Karena configure
dipanggil oleh sistem yang kontennya
dimaksudkan untuk divalidasi, ada peluang sempit bagi penyerang untuk
memperbarui image sistem dan memaksanya untuk memberikan informasi versi yang
cocok dengan image booting, tetapi bukan versi sistem yang sebenarnya. Kombinasi
verifikasi image booting, validasi dm-verity konten image
sistem, dan fakta bahwa configure
dipanggil sangat awal dalam
booting sistem akan membuat peluang ini sulit dieksploitasi.