Keystore yang didukung hardware

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

Glosarium

Berikut adalah ringkasan singkat komponen Keystore dan hubungannya.

AndroidKeyStore
Android Framework API dan komponen 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 menyediakan 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 dapat menggunakan atau mengungkapkannya.
Layanan KeyMint HAL
Server AIDL yang menerapkan HAL IKeyMintDevice, yang menyediakan akses ke TA KeyMint yang mendasarinya.
Aplikasi tepercaya (TA) KeyMint
Software yang berjalan dalam konteks yang aman, paling sering di TrustZone pada ARM SoC, yang menyediakan semua operasi kriptografi 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. Fitur 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 diberikannya 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 telah 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 telah dilakukan untuk pengguna tertentu pada waktu tertentu.

Arsitektur

Android Keystore API dan KeyMint HAL yang mendasarinya menyediakan serangkaian primitif kriptografi dasar tetapi memadai untuk memungkinkan penerapan protokol menggunakan kunci yang didukung hardware dan dikontrol aksesnya.

HAL KeyMint adalah layanan yang disediakan OEM yang digunakan oleh layanan Keystore untuk menyediakan layanan kriptografi yang didukung hardware. Untuk menjaga keamanan materi kunci pribadi, 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 yang aman, biasanya dengan menyusun dan mengurai permintaan dalam beberapa format wire yang ditentukan implementasinya.

Arsitektur yang dihasilkan akan terlihat seperti ini:

Akses ke KeyMint

Gambar 1. Akses ke KeyMint.

API HAL KeyMint memiliki level rendah, digunakan oleh komponen internal platform, dan tidak diekspos ke developer aplikasi. Java API tingkat 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. Oleh karena itu, akses ke setiap kunci biasanya dibatasi untuk aplikasi atau komponen sistem yang membuat kunci tersebut.

Domain keystore

Untuk mendukung kontrol akses ini, kunci diidentifikasi ke Keystore dengan deskriptor kunci. Deskriptor kunci ini menunjukkan domain yang dimiliki deskriptor, bersama dengan 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 kuncinumerik unik setelah kunci dimuat. ID numerik ini digunakan sebagai ID untuk deskriptor utama dalam domain KEY_ID. Namun, kontrol akses tetap 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 deskriptor kunci dalam domain GRANT. Sekali lagi, kontrol akses tetap dilakukan: meskipun aplikasi pihak ketiga menemukan ID pemberian untuk kunci penerima, aplikasi tersebut tidak dapat menggunakannya.

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

  • Domain BLOB menunjukkan bahwa tidak ada ID untuk kunci dalam deskriptor kunci; sebagai gantinya, deskriptor kunci menyimpan keyblob itu sendiri dan klien menangani penyimpanan keyblob. Ini digunakan oleh klien (misalnya, vold) yang perlu mengakses Keystore sebelum partisi data di-mount.
  • 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 deskriptor kunci Domain::SELINUX dikonfigurasi dalam file kebijakan SELinux keystore2_key_context. Setiap baris dalam file ini memetakan numerik 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 ke dalam rentang untuk mendukung partisi yang berbeda tanpa konflik:

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 super user. Hanya digunakan untuk pengujian pada build userdebug dan eng. Tidak relevan pada build pengguna.
1 shell_key T/A Namespace tersedia untuk shell. Sebagian besar digunakan untuk pengujian, tetapi juga dapat digunakan pada build pengguna dari command line.
100 vold_key T/A Ditujukan 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 melanjutkan setelah memulai ulang.

Vektor akses

Keystore memungkinkan kontrol atas operasi yang dapat dilakukan pada kunci, selain mengontrol akses 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 meng-enumerasi namespace mereka sendiri (dicakup oleh izin get_info).
lock Diperlukan untuk memberi tahu keystore bahwa perangkat dikunci, yang pada gilirannya akan mengeluarkan kunci super untuk memastikan kunci yang terikat autentikasi tidak tersedia.
unlock Diperlukan untuk memberi tahu keystore bahwa perangkat telah dibuka kuncinya, 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 OS Android.

Histori

Di Android 5 dan yang lebih rendah, Android memiliki API layanan kriptografi 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 primitif 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 kriptografi tertentu.

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

  • Skema kontrol penggunaan untuk membatasi penggunaan kunci, guna mengurangi risiko pelanggaran keamanan akibat penyalahgunaan kunci
  • Skema kontrol akses untuk mengaktifkan pembatasan kunci bagi pengguna, klien, dan rentang waktu tertentu

Android 7.0

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

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

Pengikatan versi mengikat kunci ke versi sistem operasi dan 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 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. Saat perangkat diupgrade, kunci akan di-ratchet bersama dengan 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 hardware interface definition language (HIDL) baru. Sebagai bagian dari perubahan ini, banyak jenis argumen yang berubah, meskipun jenis dan metode memiliki korespondensi satu-ke-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 secara 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 harus menemukan cara yang aman untuk mengambil item data yang relevan, serta menentukan mekanisme untuk menonaktifkan fitur secara aman dan permanen.

Android 9

Di Android 9, update mencakup:

  • Update ke Keymaster 4
  • Dukungan untuk Elemen Keamanan tersemat
  • Dukungan untuk impor kunci yang aman
  • Dukungan untuk enkripsi 3DES
  • Perubahan pada pengikatan 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 dienkapsulasi hardware
  • Dukungan opsional untuk pengesahan unik per 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 versi baru daemon sistem keystore, yang ditulis ulang di Rust dan dikenal sebagai keystore2

Android 13

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