Keystore yang didukung hardware

Ketersediaan Trusted Execution Environment (TEE) dalam sistem pada chip (SoC) menawarkan peluang bagi perangkat Android untuk menyediakan layanan keamanan yang kuat dan didukung hardware ke Android OS, ke layanan platform, dan bahkan ke aplikasi pihak ketiga (dalam bentuk ekstensi khusus Android ke Java Cryptography Architecture standar, lihat KeyGenParameterSpec).

Glosarium

Berikut adalah ringkasan singkat tentang komponen Keystore dan hubungannya.

AndroidKeyStore
API dan komponen Android Framework yang digunakan oleh aplikasi untuk mengakses fungsi Keystore. Ini adalah implementasi API Java Cryptography Architecture standar, tetapi juga menambahkan ekstensi khusus Android dan terdiri dari kode Java yang berjalan di ruang proses aplikasi itu sendiri. AndroidKeyStore memenuhi permintaan aplikasi untuk perilaku Keystore dengan meneruskannya ke daemon keystore.
daemon keystore
Daemon sistem Android yang memberikan akses ke semua fungsi Keystore melalui Binder API. Daemon ini bertanggung jawab untuk menyimpan keyblob yang dibuat oleh implementasi KeyMint (atau Keymaster) yang mendasarinya, yang berisi materi kunci rahasia, dienkripsi sehingga Keystore dapat menyimpannya, tetapi tidak menggunakannya atau mengungkapkannya.
Layanan HAL KeyMint
Server AIDL yang mengimplementasikan HAL IKeyMintDevice, yang menyediakan akses ke TA KeyMint yang mendasarinya.
Aplikasi tepercaya (TA) KeyMint
Software yang berjalan dalam konteks aman, biasanya di TrustZone pada SoC ARM, yang menyediakan semua operasi kriptografis yang aman. Aplikasi ini memiliki akses ke materi kunci mentah, dan memvalidasi semua kondisi kontrol akses pada kunci sebelum mengizinkan penggunaannya.
LockSettingsService
Komponen sistem Android yang bertanggung jawab atas autentikasi pengguna, baik sandi maupun sidik jari. Ini bukan bagian dari Keystore, tetapi relevan karena Keystore mendukung konsep kunci terikat autentikasi: kunci yang hanya dapat digunakan jika pengguna telah diautentikasi. LockSettingsService berinteraksi dengan TA Gatekeeper dan TA Sidik Jari untuk mendapatkan token autentikasi, yang disediakan ke daemon keystore, dan yang digunakan oleh TA KeyMint.
TA Gatekeeper
Komponen yang berjalan di lingkungan aman yang bertanggung jawab untuk mengautentikasi sandi pengguna dan membuat token autentikasi yang digunakan untuk membuktikan kepada TA KeyMint bahwa autentikasi dilakukan untuk pengguna tertentu pada waktu tertentu.
TA Sidik Jari
Komponen yang berjalan di lingkungan aman yang bertanggung jawab untuk mengautentikasi sidik jari pengguna dan membuat token autentikasi yang digunakan untuk membuktikan kepada TA KeyMint bahwa autentikasi dilakukan untuk pengguna tertentu pada waktu tertentu.

Arsitektur

Android Keystore API dan HAL KeyMint yang mendasarinya menyediakan kumpulan primitif kriptografis dasar tetapi memadai untuk memungkinkan implementasi protokol menggunakan kunci yang didukung hardware dan dikontrol akses.

HAL KeyMint adalah layanan yang disediakan OEM yang digunakan oleh layanan Keystore untuk menyediakan layanan kriptografis yang didukung hardware. Agar materi kunci pribadi tetap aman, implementasi HAL tidak melakukan operasi sensitif apa pun di ruang pengguna, atau bahkan di ruang kernel. Sebagai gantinya, layanan KeyMint HAL yang berjalan di Android mendelegasikan operasi sensitif ke TA yang berjalan di beberapa jenis lingkungan aman, biasanya dengan mengatur dan membatalkan pengaturan permintaan dalam beberapa format wire yang ditentukan implementasi.

Arsitektur yang dihasilkan terlihat seperti ini:

Akses ke KeyMint

Gambar 1. Akses ke KeyMint.

KeyMint HAL API bersifat mendasar, digunakan oleh komponen internal platform, dan tidak diekspos kepada developer aplikasi. Java API level tinggi yang tersedia untuk aplikasi dijelaskan di situs Android Developer.

Access control

Android Keystore menyediakan komponen pusat untuk penyimpanan dan penggunaan kunci kriptografi yang didukung hardware, baik untuk aplikasi maupun untuk komponen sistem lainnya. Dengan demikian, akses ke setiap kunci biasanya dibatasi untuk komponen aplikasi atau sistem yang membuat kunci.

Domain keystore

Untuk mendukung kontrol akses ini, kunci diidentifikasi ke Keystore dengan deskripsi kunci. Deskripsi kunci ini menunjukkan domain yang menjadi milik deskripsi, beserta identitas dalam domain tersebut.

Aplikasi Android mengakses Keystore menggunakan Java Cryptography Architecture standar, yang mengidentifikasi kunci dengan alias string. Metode identifikasi ini dipetakan ke domain APP Keystore secara internal; UID pemanggil juga disertakan untuk membedakan kunci dari aplikasi yang berbeda, sehingga mencegah satu aplikasi mengakses kunci aplikasi lain.

Secara internal, kode framework juga menerima ID kunci numerik yang unik setelah kunci dimuat. ID numerik ini digunakan sebagai ID untuk deskripsi kunci dalam domain KEY_ID. Namun, kontrol akses masih dilakukan: meskipun satu aplikasi menemukan ID kunci untuk kunci aplikasi lain, aplikasi tersebut tidak dapat menggunakannya dalam keadaan normal.

Namun, aplikasi dapat memberikan penggunaan kunci ke aplikasi lain (seperti yang diidentifikasi oleh UID). Operasi pemberian ini menampilkan ID pemberian unik, yang digunakan sebagai ID untuk deskripsi kunci dalam domain GRANT. Sekali lagi, kontrol akses masih dilakukan: meskipun aplikasi pihak ketiga menemukan ID pemberian untuk kunci penerima, aplikasi tersebut tidak dapat menggunakannya.

Keystore juga mendukung dua domain lain untuk deskripsi kunci, yang digunakan untuk komponen sistem lainnya dan tidak tersedia untuk kunci yang dibuat aplikasi:

  • Domain BLOB menunjukkan bahwa tidak ada ID untuk kunci dalam deskripsi kunci; sebagai gantinya, deskripsi kunci menyimpan keyblob itu sendiri dan klien menangani penyimpanan keyblob. Ini digunakan oleh klien (misalnya, vold) yang perlu mengakses Keystore sebelum partisi data dipasang.
  • Domain SELINUX memungkinkan komponen sistem berbagi kunci, dengan akses yang diatur oleh ID numerik yang sesuai dengan label SELinux (lihat kebijakan SELinux untuk keystore_key).

Kebijakan SELinux untuk keystore_key

Nilai ID yang digunakan untuk deskripsi kunci Domain::SELINUX dikonfigurasi dalam file kebijakan SELinux keystore2_key_context. Setiap baris dalam file ini memetakan angka ke label SELinux, misalnya:

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share Keystore keys.
102            u:object_r:wifi_key:s0

Komponen yang memerlukan akses ke kunci dengan ID 102 di domain SELINUX harus memiliki kebijakan SELinux yang sesuai. Misalnya, untuk mengizinkan wpa_supplicant mendapatkan dan menggunakan kunci ini, tambahkan baris berikut ke hal_wifi_supplicant.te:

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

ID numerik untuk kunci Domain::SELINUX dibagi menjadi rentang untuk mendukung partisi yang berbeda tanpa tabrakan:

Partisi Rentang File konfigurasi
Sistem 0 ... 9.999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Sistem yang Diperluas 10.000 ... 19.999 /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Produk 20.000 ... 29.999 /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Vendor 30.000 ... 39.999 /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Nilai spesifik berikut telah ditentukan untuk partisi sistem:

ID Ruangnama Label SEPolicy UID Deskripsi
0 su_key T/A Kunci superuser. Hanya digunakan untuk pengujian pada build userdebug dan eng. Tidak relevan pada build pengguna.
1 shell_key T/A Namespace yang tersedia untuk shell. Sebagian besar digunakan untuk pengujian, tetapi juga dapat digunakan pada build pengguna dari command line.
100 vold_key T/A Dimaksudkan untuk digunakan oleh vold.
101 odsign_key T/A Digunakan oleh daemon penandatanganan di perangkat.
102 wifi_key AID_WIFI(1010) Digunakan oleh subsistem Wi-Fi Android termasuk wpa_supplicant.
103 locksettings_key T/A Digunakan oleh LockSettingsService
120 resume_on_reboot_key AID_SYSTEM(1000) Digunakan oleh server sistem Android untuk mendukung kelanjutan saat memulai ulang.

Vektor akses

Keystore memungkinkan kontrol atas operasi yang dapat dilakukan pada kunci, selain mengontrol akses secara keseluruhan ke kunci. Izin keystore2_key dijelaskan dalam file KeyPermission.aidl.

Izin sistem

Selain kontrol akses per kunci yang dijelaskan dalam kebijakan SELinux untuk keystore_key, tabel berikut menjelaskan izin SELinux lainnya yang diperlukan untuk melakukan berbagai operasi sistem dan pemeliharaan:

Izin Arti
add_auth Diperlukan untuk menambahkan token autentikasi ke Keystore; digunakan oleh penyedia autentikasi seperti Gatekeeper atau BiometricManager.
clear_ns Diperlukan untuk menghapus semua kunci dalam namespace tertentu; digunakan sebagai operasi pemeliharaan saat aplikasi di-uninstal.
list Diperlukan oleh sistem untuk menghitung kunci berdasarkan berbagai properti, seperti kepemilikan atau apakah kunci tersebut terikat autentikasi. Izin ini tidak diperlukan oleh pemanggil yang menghitung namespace mereka sendiri (tercakup dalam izin get_info).
lock Diperlukan untuk memberi tahu keystore bahwa perangkat dikunci, yang pada akhirnya akan mengeluarkan kunci super untuk memastikan kunci terikat autentikasi tidak tersedia.
unlock Diperlukan untuk memberi tahu keystore bahwa perangkat telah dibuka kuncinya, sehingga memulihkan akses ke kunci super yang melindungi kunci terikat autentikasi.
reset Diperlukan untuk mereset Keystore ke setelan default pabrik, menghapus semua kunci yang tidak penting untuk fungsi Android OS.

Histori

Di Android 5 dan yang lebih lama, Android memiliki API layanan cryptographic sederhana yang didukung hardware, yang disediakan oleh Keymaster hardware abstraction layer (HAL) versi 0.2 dan 0.3. Keystore menyediakan operasi penandatanganan dan verifikasi digital, serta pembuatan dan impor pasangan kunci penandatanganan asimetris. Hal ini sudah diterapkan di banyak perangkat, tetapi ada banyak tujuan keamanan yang tidak dapat dicapai dengan mudah hanya dengan API tanda tangan. Android 6.0 memperluas Keystore API untuk menyediakan berbagai kemampuan yang lebih luas.

Android 6.0

Di Android 6.0, Keymaster 1.0 menambahkan primitive kriptografi simetris, AES dan HMAC, serta sistem kontrol akses untuk kunci yang didukung hardware. Kontrol akses ditentukan selama pembuatan kunci dan diterapkan selama masa aktif kunci. Kunci dapat dibatasi agar hanya dapat digunakan setelah pengguna diautentikasi, dan hanya untuk tujuan tertentu atau dengan parameter kriptografis yang ditentukan.

Selain memperluas rentang primitif kriptografi, Keystore di Android 6.0 menambahkan hal berikut:

  • Skema kontrol penggunaan untuk memungkinkan penggunaan kunci dibatasi, guna mengurangi risiko penyusupan keamanan karena penyalahgunaan kunci
  • Skema kontrol akses untuk mengaktifkan pembatasan kunci ke pengguna, klien, dan rentang waktu yang ditentukan

Android 7.0

Di Android 7.0, Keymaster 2 menambahkan dukungan untuk pengesahan kunci dan binding versi.

Pengesahan kunci menyediakan sertifikat kunci publik yang berisi deskripsi mendetail tentang kunci dan kontrol aksesnya, untuk membuat keberadaan kunci dalam hardware yang aman dan konfigurasinya dapat diverifikasi dari jarak jauh.

Penautan versi mengikat kunci ke sistem operasi dan versi tingkat patch. 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. Saat perangkat diupgrade, kunci akan terus maju bersama perangkat, tetapi setiap pengembalian perangkat ke rilis sebelumnya akan menyebabkan kunci tidak dapat digunakan.

Android 8.0

Di Android 8.0, Keymaster 3 bertransisi dari HAL struktur C gaya lama ke antarmuka HAL C++ yang dihasilkan dari definisi dalam bahasa definisi antarmuka hardware (HIDL) baru. Sebagai bagian dari perubahan, banyak jenis argumen yang berubah, meskipun jenis dan metode memiliki korespondensi satu-satu dengan jenis lama dan metode struct HAL.

Selain revisi antarmuka ini, Android 8.0 memperluas fitur pengesahan Keymaster 2 untuk mendukung pengesahan ID. Pengesahan ID menyediakan mekanisme terbatas dan opsional untuk mengesahkan ID hardware dengan kuat, seperti nomor seri perangkat, nama produk, dan ID ponsel (IMEI atau MEID). Untuk menerapkan penambahan ini, Android 8.0 mengubah skema pengesahan ASN.1 untuk menambahkan pengesahan ID. Implementasi Keymaster perlu menemukan beberapa cara aman untuk mengambil item data yang relevan, serta menentukan mekanisme untuk menonaktifkan fitur secara aman dan permanen.

Android 9

Di Android 9, update mencakup:

  • Mengupdate ke Keymaster 4
  • Dukungan untuk Elemen Aman tersemat
  • Dukungan untuk impor kunci yang aman
  • Dukungan untuk enkripsi 3DES
  • Perubahan pada binding versi sehingga boot.img dan system.img memiliki versi yang ditetapkan secara terpisah untuk memungkinkan update independen

Android 10

Android 10 memperkenalkan Keymaster HAL versi 4.1, yang menambahkan:

  • Dukungan untuk kunci yang hanya dapat digunakan saat perangkat tidak terkunci
  • Dukungan untuk kunci yang hanya dapat digunakan pada tahap booting awal
  • Dukungan opsional untuk kunci penyimpanan yang digabungkan dengan hardware
  • Dukungan opsional untuk pengesahan unik perangkat di StrongBox

Android 12

Android 12 memperkenalkan KeyMint HAL baru, yang menggantikan Keymaster HAL tetapi menyediakan fungsi yang serupa. Selain semua fitur di atas, HAL KeyMint juga mencakup:

  • Dukungan untuk perjanjian kunci ECDH
  • Dukungan untuk kunci pengesahan yang ditentukan pengguna
  • Dukungan untuk kunci dengan jumlah penggunaan terbatas

Android 12 juga menyertakan daemon sistem keystore versi baru, yang ditulis ulang di Rust dan dikenal sebagai keystore2

Android 13

Android 13 menambahkan KeyMint HAL v2, yang menambahkan dukungan untuk Curve25519 untuk penandatanganan dan kesepakatan kunci.