Di Keymaster 1, semua kunci keymaster terikat secara kriptografis ke perangkat Root of Trust, atau kunci Booting Terverifikasi. Di Keymaster 2 dan 3, semua juga terikat dengan sistem operasi dan tingkat {i>patch<i} dari {i>image<i} sistem. Hal ini memastikan bahwa penyerang yang menemukan kelemahan pada sistem atau perangkat lunak TEE tidak dapat melakukan {i>rollback<i} perangkat ke kelompok yang rentan dan menggunakan kunci yang dibuat dengan versi yang lebih baru. Selain itu, ketika sebuah kunci dengan versi dan level patch tertentu digunakan pada perangkat yang telah diupgrade ke versi atau level {i>patch<i} yang lebih baru, kunci tersebut diupgrade sebelum dapat digunakan, dan kunci versi sebelumnya menjadi tidak valid. Dengan cara ini, karena perangkat itu di-upgrade, kunci akan "ratchet" bergerak maju bersama perangkat, tetapi mengembalikan perangkat ke rilis sebelumnya akan menyebabkan kunci tidak dapat digunakan.
Untuk mendukung struktur modular Treble dan memutus binding system.img ke {i>boot.img<i}, Keymaster 4, mengubah model binding versi kunci agar memiliki {i>patch<i} untuk setiap partisi. Hal ini memungkinkan setiap partisi diupdate secara independen, sambil tetap memberikan perlindungan rollback.
Di Android 9, boot
, system
, dan vendor
masing-masing partisi
memiliki level {i>patch<i} mereka sendiri.
- Perangkat dengan Android Verified Boot (AVB) dapat menempatkan semua level patch
dan versi sistem di vbmeta, sehingga {i>bootloader<i}
dapat menyediakannya untuk
Keymaster. Untuk partisi berantai, info versi untuk partisi akan
berada di vbmeta berantai. Secara umum, informasi versi harus dalam
vbmeta struct
yang berisi data verifikasi (hash atau hashtree) untuk partisi tertentu. - Di perangkat tanpa AVB:
- Implementasi Booting Terverifikasi harus memberikan hash versi metadata ke bootloader, sehingga bootloader dapat menyediakan hash ke Keymaster.
boot.img
dapat terus menyimpan level patch di headersystem.img
dapat terus menyimpan level patch dan versi OS dalam mode hanya baca propertivendor.img
menyimpan level patch di properti hanya bacaro.vendor.build.version.security_patch
.- Bootloader dapat memberikan hash semua data yang divalidasi dengan booting terverifikasi menjadi {i>keymaster<i}.
- Di Android 9, gunakan tag berikut untuk menyediakan 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 menangani semua level patch secara independen. Kunci adalah
dapat digunakan jika semua info versi cocok dengan nilai yang terkait dengan kunci, dan
IKeymaster::upgradeDevice()
di-roll ke level patch yang lebih tinggi jika diperlukan.
Perubahan HAL
Untuk mendukung pengikatan versi dan pengesahan versi, Android 7.1 menambahkan
tag Tag::OS_VERSION
dan Tag::OS_PATCHLEVEL
, serta
metode configure
dan upgradeKey
. Tag versi
ditambahkan secara otomatis oleh implementasi Keymaster 2+ ke semua implementasi yang baru dibuat
kunci (atau kunci yang diperbarui). Selanjutnya, segala upaya untuk
menggunakan kunci yang tidak memiliki OS
versi atau level {i>patch<i} yang cocok dengan
versi OS sistem atau level {i>patch<i} saat ini,
masing-masing, ditolak dengan ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
adalah nilai UINT
yang mewakili
bagian utama, minor, dan sub-kecil dari versi sistem Android seperti MMmmss,
dengan MM adalah versi utama, mm adalah versi minor, dan ss adalah versi sub-minor
. Misalnya 6.1.2 akan ditampilkan sebagai 060102.
Tag::OS_PATCHLEVEL
adalah nilai UINT
yang mewakili
tahun dan bulan pembaruan terakhir ke sistem sebagai YYYYMM, di mana YYYY adalah
tahun dengan empat digit dan MM adalah bulan dengan dua digit. Misalnya, Maret 2016 akan menjadi
yang direpresentasikan sebagai 201603.
Kunci Upgrade
Untuk mengizinkan kunci diupgrade ke versi OS dan level patch sistem yang baru
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 akan mencakupTag::APPLICATION_ID
danTag::APPLICATION_DATA
, yang diperlukan untuk mendekripsi kunci blob, 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
jika tidak valid, kueri akan menampilkan ErrorCode::INVALID_KEY_BLOB
. Jika ya
dipanggil dengan kunci yang tingkat {i>patch<i}-nya
lebih besar dari nilai sistem saat ini,
kueri akan menghasilkan ErrorCode::INVALID_ARGUMENT
. Jika dipanggil dengan kunci
yang versi OS-nya lebih besar dari nilai sistem saat ini, dan nilai sistem
bukan nol, maka akan menampilkan ErrorCode::INVALID_ARGUMENT
. Versi OS
upgrade dari selain nol
ke nol diperbolehkan. Jika terjadi error
berkomunikasi dengan dunia aman, sistem ini mengembalikan nilai kesalahan yang sesuai (mis.
ErrorCode::SECURE_HW_ACCESS_DENIED
,
ErrorCode::SECURE_HW_BUSY
). Jika tidak, metode ini akan
ErrorCode::OK
dan menampilkan blob kunci baru di
upgradedKeyBlob
.
keyBlobToUpgrade
tetap valid setelah upgradeKey
dan secara teoretis dapat digunakan
lagi jika perangkat telah didowngrade. Di beberapa
praktik, keystore umumnya memanggil deleteKey
pada
keyBlobToUpgrade
blob segera setelah panggilan ke
upgradeKey
. Jika keyBlobToUpgrade
memiliki tag
Tag::ROLLBACK_RESISTANT
, lalu upgradedKeyBlob
harus
juga memilikinya (dan harus tahan rollback).
Konfigurasi aman
Untuk mengimplementasikan pengikatan versi, TA {i>keymaster<i} perlu cara untuk menerima versi OS saat ini dan level {i>patch<i} (informasi versi), dan untuk memastikan bahwa informasi yang diterimanya sangat cocok dengan informasi tentang sistem file.
Untuk mendukung pengiriman informasi versi yang aman ke TA, OS_VERSION
kolom telah ditambahkan ke header image booting. Build image booting
skrip akan secara otomatis mengisi kolom ini. OEM dan pelaksana TA keymaster
harus bekerja sama untuk memodifikasi bootloader perangkat guna mengekstrak versinya
informasi dari boot image dan meneruskannya ke TA sebelum
sistem di-{i>booting<i}. Hal ini untuk memastikan bahwa penyerang tidak
dapat mengganggu penyediaan
informasi versi kepada TA.
Anda juga perlu memastikan bahwa image sistem memiliki versi yang sama informasi seperti boot image. Untuk itu, metode konfigurasi telah ditambahkan ke HAL {i>keymaster<i}:
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 mengkonfigurasi, TA mengembalikan
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
{i>bootloader<i}. Jika informasi versi tidak cocok,
configure
menampilkan ErrorCode::INVALID_ARGUMENT
, dan semua
metode keymaster lainnya terus memunculkan
ErrorCode::KEYMASTER_NOT_CONFIGURED
. Jika informasinya cocok,
configure
menampilkan ErrorCode::OK
, dan keymaster lainnya
metode tersebut mulai berfungsi secara normal.
Panggilan berikutnya ke configure
menampilkan nilai yang sama dengan yang ditampilkan oleh
panggilan pertama, dan tidak
mengubah status {i>keymaster<i}. Perhatikan bahwa proses ini
mengharuskan semua OTA memperbarui
sistem dan image booting; fungsi tersebut tidak dapat diperbarui
secara terpisah untuk menjaga
informasi versi tetap sinkron.
Karena configure
akan dipanggil oleh sistem yang isinya
dimaksudkan untuk memvalidasi, maka ada
peluang kecil bagi penyerang untuk
menyusupi {i>image<i} sistem dan memaksanya
untuk memberikan informasi versi yang
cocok dengan {i>boot image<i}, tetapi
bukanlah versi sistem yang sebenarnya. Tujuan
kombinasi verifikasi image boot, validasi dm-verity dari image sistem
konten, dan fakta bahwa configure
dipanggil sangat awal dalam
{i>booting<i} sistem seharusnya membuat jendela
peluang ini sulit untuk dieksploitasi.