Binding versi

Di Keymaster 1, semua kunci Keymaster terikat secara kriptografi ke Root of Trust perangkat, atau kunci Booting Terverifikasi. Di Keymaster 2 dan 3, semua kunci juga terikat ke sistem operasi dan tingkat patch image sistem. Hal ini memastikan bahwa penyerang yang menemukan kelemahan dalam versi lama software sistem atau TEE tidak dapat me-roll back perangkat ke versi yang rentan dan menggunakan kunci yang dibuat dengan versi yang lebih baru. Selain itu, saat kunci dengan versi dan tingkat patch tertentu digunakan di perangkat yang telah diupgrade ke versi atau tingkat patch yang lebih baru, kunci tersebut akan diupgrade sebelum dapat digunakan, dan versi kunci sebelumnya akan dibatalkan. Dengan cara ini, saat perangkat diupgrade, kunci akan *bergeser* ke depan bersama dengan perangkat, tetapi setiap pengembalian perangkat ke rilis sebelumnya akan menyebabkan kunci tidak dapat digunakan.

Untuk mendukung struktur modular Treble dan memutus 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.

Untuk menerapkan binding versi ini, aplikasi tepercaya (TA) KeyMint memerlukan cara untuk menerima versi OS dan tingkat patch saat ini secara aman, serta memastikan bahwa informasi yang diterimanya cocok dengan semua informasi tentang sistem yang berjalan.

  • Perangkat dengan Android Booting Terverifikasi (AVB) dapat menempatkan semua tingkat patch dan versi sistem di vbmeta, sehingga bootloader dapat memberikannya ke Keymaster. Untuk partisi yang dirantai, info versi untuk partisi berada di vbmeta yang dirantai. Secara umum, informasi versi harus berada di vbmeta struct yang berisi data verifikasi (hash atau hashtree) untuk partisi tertentu.
  • Di perangkat tanpa AVB:
    • Implementasi Booting Terverifikasi harus memberikan hash metadata versi ke bootloader, sehingga bootloader dapat memberikan hash ke Keymaster.
    • boot.img dapat terus menyimpan tingkat patch di header
    • system.img dapat terus menyimpan tingkat patch dan versi OS di properti hanya baca
    • vendor.img menyimpan tingkat patch di properti hanya baca ro.vendor.build.version.security_patch.
    • Bootloader dapat memberikan hash 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: partisi vendor
    • BOOT_PATCH_LEVEL: partisi boot
    • OS_PATCH_LEVEL dan OS_VERSION: system partisi. (OS_VERSION dihapus dari header boot.img.
  • Implementasi Keymaster harus memperlakukan semua tingkat patch secara independen. 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 diupdate). Selain itu, setiap upaya untuk menggunakan kunci yang tidak memiliki versi OS atau tingkat patch yang cocok dengan versi OS atau tingkat patch sistem 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 direpresentasikan sebagai 201603.

UpgradeKey

Untuk mengizinkan kunci diupgrade ke versi OS dan tingkat patch image 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. Parameter ini mencakup Tag::APPLICATION_ID dan Tag::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, metode ini akan menampilkan ErrorCode::INVALID_KEY_BLOB. Jika dipanggil dengan kunci yang tingkat patch-nya lebih besar dari nilai sistem saat ini, metode ini akan menampilkan ErrorCode::INVALID_ARGUMENT. Jika dipanggil dengan kunci yang versi OS-nya lebih besar dari nilai sistem saat ini, dan nilai sistemnya bukan nol, metode ini akan menampilkan ErrorCode::INVALID_ARGUMENT. Upgrade versi OS dari bukan nol ke nol diizinkan. Jika terjadi error saat berkomunikasi dengan dunia yang aman, metode ini akan menampilkan nilai error yang sesuai (misalnya, ErrorCode::SECURE_HW_ACCESS_DENIED, ErrorCode::SECURE_HW_BUSY). Jika tidak, metode ini akan menampilkan ErrorCode::OK dan menampilkan blob kunci baru di upgradedKeyBlob.

keyBlobToUpgrade tetap valid setelah panggilan upgradeKey, dan secara teoretis dapat digunakan lagi jika perangkat di-downgrade. 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, Keymaster TA memerlukan cara untuk menerima versi OS dan tingkat patch saat ini (informasi versi) secara aman, serta memastikan bahwa informasi yang diterimanya sangat cocok dengan informasi tentang sistem yang berjalan.

Untuk mendukung pengiriman informasi versi yang aman ke TA, OS_VERSION kolom telah ditambahkan ke header boot image. Skrip build image booting otomatis mengisi kolom ini. OEM dan pengimplementasi Keymaster TA harus bekerja sama untuk mengubah 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 harus memastikan bahwa image sistem memiliki informasi versi yang sama dengan boot image. Untuk itu, metode konfigurasi telah ditambahkan ke Keymaster HAL:

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 lainnya. Jika metode lain dipanggil sebelum konfigurasi, TA akan menampilkan ErrorCode::KEYMASTER_NOT_CONFIGURED.

Saat pertama kali configure dipanggil setelah perangkat di-booting, metode ini harus memverifikasi bahwa informasi versi yang diberikan cocok dengan informasi 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 akan mulai berfungsi secara normal.

Panggilan berikutnya ke configure akan menampilkan nilai yang sama dengan yang ditampilkan oleh panggilan pertama, dan tidak mengubah status Keymaster.

Karena configure dipanggil oleh sistem yang kontennya akan divalidasi, penyerang memiliki peluang kecil untuk membahayakan image sistem dan memaksanya memberikan informasi versi yang cocok dengan boot image, 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.