Binding Versi

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 header
    • system.img dapat terus menyimpan level patch dan versi OS dalam mode hanya baca properti
    • vendor.img menyimpan level patch di properti hanya baca ro.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: partisi vendor
    • BOOT_PATCH_LEVEL: partisi boot
    • OS_PATCH_LEVEL dan OS_VERSION: Partisi system. (OS_VERSION dihapus dari header boot.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 perangkat
  • keyBlobToUpgrade adalah kunci yang perlu diupgrade
  • upgradeParams adalah parameter yang diperlukan untuk mengupgrade kunci. Ini akan mencakup Tag::APPLICATION_ID dan Tag::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.