Mulai Android 12, modul Android Runtime (ART) adalah modul Mainline. Mengupdate modul mungkin mengharuskan modul tersebut mem-build ulang artefak kompilasi ahead-of-time (AOT) dari jar bootclasspath dan server sistem. Karena artefak ini sensitif terhadap keamanan, Android 12 menggunakan fitur yang disebut penandatanganan di perangkat untuk mencegah artefak ini dirusak. Halaman ini membahas arsitektur penandatanganan di perangkat dan interaksinya dengan fitur keamanan Android lainnya.
Desain tingkat tinggi
Penandatanganan di perangkat memiliki dua komponen inti:
odrefresh
adalah bagian dari modul ART Mainline. Alat ini bertanggung jawab untuk membuat artefak runtime. Alat ini memeriksa artefak yang ada dengan versi modul ART, jar bootclasspath, dan jar server sistem yang diinstal untuk menentukan apakah artefak tersebut sudah yang terbaru atau perlu dibuat ulang. Jika perlu dibuat ulang,odrefresh
akan membuatnya dan menyimpannya.odsign
adalah biner yang merupakan bagian dari platform Android. Proses ini berjalan selama booting awal, tepat setelah partisi/data
dipasang. Tanggung jawab utamanya adalah memanggilodrefresh
untuk memeriksa apakah ada artefak yang perlu dibuat atau diperbarui. Untuk artefak baru atau yang diperbarui yang dihasilkanodrefresh
,odsign
akan menghitung fungsi hash. Hasil komputasi hash tersebut disebut ringkasan file. Untuk artefak yang sudah ada,odsign
memverifikasi bahwa ringkasan artefak yang ada cocok dengan ringkasan yang telah dihitungodsign
sebelumnya. Hal ini memastikan bahwa artefak tidak dirusak.
Dalam kondisi error, seperti saat ringkasan untuk file tidak cocok,
odrefresh
dan odsign
akan menghapus semua artefak yang ada di /data
dan
mencoba membuatnya ulang. Jika gagal, sistem akan kembali ke mode JIT.
odrefresh
dan odsign
dilindungi oleh dm-verity
, dan merupakan bagian dari
rantai Verified Boot Android.
Komputasi ringkasan file dengan fs-verity
fs-verity adalah fitur kernel Linux yang melakukan verifikasi data file berbasis hierarki Merkle. Mengaktifkan fs-verity pada file menyebabkan sistem file membuat hierarki Merkle pada data file menggunakan hash SHA-256, menyimpannya di lokasi tersembunyi bersama file, dan menandai file sebagai hanya baca. fs-verity otomatis memverifikasi data file terhadap hierarki Merkle sesuai permintaan saat dibaca. fs-verity menyediakan hash root hierarki Merkle sebagai nilai yang disebut ringkasan file fs-verity, dan fs-verity memastikan bahwa data apa pun yang dibaca dari file konsisten dengan ringkasan file ini.
odsign
menggunakan fs-verity untuk meningkatkan performa booting dengan mengoptimalkan
autentikasi kriptografis artefak yang dikompilasi di perangkat pada waktu booting. Saat
artefak dibuat, odsign
akan mengaktifkan fs-verity di artefak tersebut. Saat odsign
memverifikasi artefak, odsign
akan memverifikasi ringkasan file fs-verity, bukan hash
file lengkap. Dengan demikian, Anda tidak perlu membaca dan melakukan hashing data lengkap
artefak pada waktu booting. Sebagai gantinya, data artefak di-hash sesuai permintaan oleh fs-verity
saat digunakan, berdasarkan blok demi blok.
Pada perangkat yang kernel-nya tidak mendukung fs-verity, odsign
akan kembali ke
penghitungan ringkasan file di ruang pengguna. odsign
menggunakan algoritma hash berbasis
pohon Merkle yang sama dengan fs-verity, sehingga ringkasannya sama dalam kedua kasus tersebut.
fs-verity diperlukan di semua perangkat yang diluncurkan dengan Android 11 dan yang lebih tinggi.
Penyimpanan ringkasan file
odsign
menyimpan ringkasan file artefak dalam file terpisah yang disebut
odsign.info
. Untuk memastikan odsign.info
tidak dimodifikasi, odsign.info
ditandatangani dengan kunci penandatanganan yang memiliki properti keamanan penting. Secara
khusus, kunci hanya dapat dibuat dan digunakan selama booting awal, saat
hanya kode tepercaya yang berjalan; lihat Kunci penandatanganan tepercaya untuk mengetahui detailnya.
Verifikasi ringkasan file
Pada setiap booting, jika odrefresh
menentukan bahwa artefak yang ada
sudah yang terbaru, odsign
akan memastikan bahwa file tersebut tidak dimodifikasi sejak
file tersebut dibuat. odsign
melakukannya dengan memverifikasi ringkasan file. Pertama, verifikasi tanda tangan odsign.info
. Jika tanda tangan valid, odsign
akan memverifikasi bahwa ringkasan setiap file cocok dengan ringkasan yang sesuai
di odsign.info
.
Kunci penandatanganan tepercaya
Android 12 memperkenalkan fitur Keystore baru yang disebut kunci tahap booting yang mengatasi masalah keamanan berikut:
- Apa yang mencegah penyerang menggunakan kunci penandatanganan kami untuk menandatangani
versi
odsign.info
mereka sendiri? - Apa yang mencegah penyerang membuat kunci penandatanganan sendiri dan menggunakannya
untuk menandatangani versi
odsign.info
mereka sendiri?
Kunci tahap booting membagi siklus booting Android menjadi beberapa level, dan secara kriptografis
mengikat pembuatan dan penggunaan kunci ke level yang ditentukan. odsign
membuat
kunci penandatanganan pada tingkat awal, saat hanya kode tepercaya yang berjalan, yang dilindungi
melalui dm-verity
.
Level tahap booting diberi nomor dari 0 hingga angka ajaib 1000000000. Selama
proses booting Android, Anda dapat meningkatkan level booting dengan menetapkan properti
sistem dari init.rc
. Misalnya, kode berikut menetapkan level booting ke
10:
setprop keystore.boot_level 10
Klien Keystore dapat membuat kunci yang terikat dengan level booting tertentu. Misalnya, jika Anda membuat kunci untuk level booting 10, kunci tersebut hanya dapat digunakan saat perangkat berada di level booting 10.
odsign
menggunakan level booting 30, dan kunci penandatanganan yang dibuatnya terikat dengan
level booting tersebut. Sebelum menggunakan kunci untuk menandatangani artefak, odsign
akan memverifikasi bahwa
kunci terikat dengan level booting 30.
Hal ini mencegah dua serangan yang dijelaskan sebelumnya di bagian ini:
- Penyerang tidak dapat menggunakan kunci yang dihasilkan, karena pada saat penyerang memiliki kesempatan untuk menjalankan kode berbahaya, level booting telah meningkat melebihi 30, dan Keystore menolak operasi yang menggunakan kunci.
- Penyerang tidak dapat membuat kunci baru, karena pada saat penyerang memiliki peluang
untuk menjalankan kode berbahaya, tingkat booting telah meningkat di atas 30, dan
Keystore menolak untuk membuat kunci baru dengan tingkat booting tersebut. Jika penyerang
membuat kunci baru yang tidak terikat dengan tingkat booting 30,
odsign
akan menolaknya.
Keystore memastikan bahwa tingkat booting diterapkan dengan benar. Bagian berikut membahas lebih detail cara melakukannya untuk berbagai versi Keymaster.
Implementasi Keymaster 4.0
Versi Keymaster yang berbeda menangani implementasi kunci tahap booting dengan cara yang berbeda. Pada perangkat dengan TEE/Strongbox Keymaster 4.0, Keymaster menangani penerapan sebagai berikut:
- Saat pertama kali di-booting, Keystore membuat kunci simetris K0 dengan tag
MAX_USES_PER_BOOT
yang ditetapkan ke1
. Artinya, kunci hanya dapat digunakan sekali per booting. - Selama booting, jika level booting ditingkatkan, kunci baru untuk level booting
tersebut dapat dibuat dari K0 menggunakan fungsi HKDF:
Ki+i=HKDF(Ki, "some_fixed_string")
. Misalnya, jika Anda berpindah dari level booting 0 ke level booting 10, HKDF akan dipanggil 10 kali untuk mendapatkan K10 dari K0. Saat level booting berubah, kunci untuk level booting sebelumnya akan dihapus dari memori, dan kunci yang terkait dengan level booting sebelumnya tidak lagi tersedia.
Kunci K0 adalah kunci
MAX_USES_PER_BOOT=1
. Artinya, kunci tersebut juga tidak dapat digunakan nanti saat booting, karena setidaknya satu transisi tingkat booting (ke tingkat booting akhir) selalu terjadi.
Saat klien Keystore seperti odsign
meminta kunci untuk dibuat di level booting
i
, blob-nya dienkripsi dengan kunci Ki
. Karena Ki
tidak tersedia
setelah level booting i
, kunci ini tidak dapat dibuat atau didekripsi di tahap
booting berikutnya.
Implementasi Keymaster 4.1 dan KeyMint 1.0
Implementasi Keymaster 4.1 dan KeyMint 1.0 sebagian besar sama dengan
implementasi Keymaster 4.0. Perbedaan utamanya adalah K0 bukan
kunci MAX_USES_PER_BOOT
, tetapi kunci EARLY_BOOT_ONLY
, yang diperkenalkan di
Keymaster 4.1. Kunci EARLY_BOOT_ONLY
hanya dapat digunakan selama fase awal
booting, saat tidak ada kode yang tidak tepercaya yang berjalan. Hal ini memberikan tingkat perlindungan
tambahan: dalam penerapan Keymaster 4.0, penyerang yang membahayakan
sistem file dan SELinux dapat mengubah database Keystore untuk membuat
kunci MAX_USES_PER_BOOT=1
-nya sendiri untuk menandatangani artefak. Serangan semacam itu tidak mungkin
dengan implementasi Keymaster 4.1 dan KeyMint 1.0, karena
kunci EARLY_BOOT_ONLY
hanya dapat dibuat selama booting awal.
Komponen publik dari kunci penandatanganan tepercaya
odsign
mengambil komponen kunci publik dari kunci penandatanganan dari Keystore.
Namun, Keystore tidak mengambil kunci publik tersebut dari TEE/SE yang menyimpan
kunci pribadi yang sesuai. Sebagai gantinya, server mengambil kunci publik dari
database di disk-nya sendiri. Artinya, penyerang yang membahayakan sistem
file dapat mengubah database Keystore agar berisi kunci publik yang merupakan bagian
dari pasangan kunci publik/pribadi yang berada di bawah kendali mereka.
Untuk mencegah serangan ini, odsign
membuat kunci HMAC tambahan dengan
tingkat booting yang sama dengan kunci penandatanganan. Kemudian, saat membuat kunci penandatanganan, odsign
menggunakan kunci HMAC ini untuk membuat tanda tangan kunci publik dan menyimpannya di
disk. Pada booting berikutnya, saat mengambil kunci publik dari kunci penandatanganan, sistem
akan menggunakan kunci HMAC untuk memverifikasi bahwa tanda tangan di disk cocok dengan tanda tangan
kunci publik yang diambil. Jika cocok, kunci publik dapat dipercaya, karena
kunci HMAC hanya dapat digunakan di tingkat booting awal sehingga tidak dapat
dibuat oleh penyerang.