Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Keystore yang didukung perangkat keras

Ketersediaan lingkungan eksekusi tepercaya dalam sistem pada chip (SoC) menawarkan peluang bagi perangkat Android untuk menyediakan layanan keamanan yang kuat dan didukung perangkat keras ke OS Android, ke layanan platform, dan bahkan ke aplikasi pihak ketiga. Pengembang mencari ekstensi Android-spesifik harus pergi ke android.security.keystore .

Sebelum Android 6.0, Android telah memiliki API layanan kripto sederhana yang didukung perangkat keras, yang disediakan oleh Keymaster Hardware Abstraction Layer (HAL) versi 0.2 dan 0.3. Keystore menyediakan operasi penandatanganan dan verifikasi digital, ditambah pembuatan dan impor pasangan kunci penandatanganan asimetris. Ini sudah diterapkan di banyak perangkat, tetapi ada banyak tujuan keamanan yang tidak dapat dicapai dengan mudah hanya dengan API tanda tangan. Keystore di Android 6.0 memperluas API Keystore untuk menyediakan jangkauan kemampuan yang lebih luas.

Di Android 6.0, Keystore menambahkan primitif simetris kriptografi , AES dan HMAC, dan sistem kontrol akses untuk kunci hardware yang didukung. Kontrol akses ditentukan selama pembuatan kunci dan diterapkan selama masa pakai kunci. Kunci dapat dibatasi agar dapat digunakan hanya setelah pengguna diautentikasi, dan hanya untuk tujuan tertentu atau dengan parameter kriptografi tertentu. Untuk informasi lebih lanjut, lihat Otorisasi Tags dan Fungsi halaman.

Selain memperluas jangkauan kriptografi primitif, Keystore di Android 6.0 menambahkan yang berikut:

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

Di Android 7.0, Keymaster 2 menambahkan dukungan untuk pengesahan kunci dan pengikatan versi. Pengesahan kunci memberikan sertifikat kunci publik yang berisi penjelasan rinci tentang kunci dan kontrol akses, untuk membuat keberadaan kunci dalam hardware aman dan konfigurasi jarak jauh diverifikasi.

Versi mengikat kunci mengikat untuk sistem operasi dan versi patch level. Ini memastikan bahwa penyerang yang menemukan kelemahan dalam sistem versi lama atau perangkat lunak TEE tidak dapat mengembalikan perangkat ke versi yang rentan dan menggunakan kunci yang dibuat dengan versi yang lebih baru. Selain itu, ketika kunci dengan versi dan level tambalan tertentu digunakan pada perangkat yang telah ditingkatkan ke versi atau tingkat tambalan yang lebih baru, kunci dimutakhirkan sebelum dapat digunakan, dan versi kunci sebelumnya menjadi tidak valid. Saat perangkat ditingkatkan, kunci "ratchet" maju bersama dengan perangkat, tetapi setiap pengembalian perangkat ke rilis sebelumnya menyebabkan kunci tidak dapat digunakan.

Di Android 8.0, Keymaster 3 bertransisi dari Hardware Abstraction Layer (HAL) gaya lama ke antarmuka C++ HAL yang dihasilkan dari definisi di Hardware Interface Definition Language (HIDL) baru. Sebagai bagian dari perubahan, banyak tipe argumen berubah, meskipun tipe dan metode memiliki korespondensi satu-ke-satu dengan tipe lama dan metode struct HAL. Lihat Fungsi halaman untuk rincian lebih lanjut.

Selain revisi antarmuka ini, Android 8.0 diperpanjang fitur pengesahan Keymaster 2 untuk dukungan ID pengesahan . Pengesahan ID menyediakan mekanisme terbatas dan opsional untuk membuktikan secara kuat pengenal perangkat keras, seperti nomor seri perangkat, nama produk, dan ID telepon (IMEI/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 untuk menentukan mekanisme untuk menonaktifkan fitur secara aman dan permanen.

Di Android 9, pembaruan termasuk:

  • Update untuk Keymaster 4
  • Dukungan untuk Elemen Aman yang disematkan
  • 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 pembaruan independen

Glosarium

Berikut adalah ikhtisar singkat tentang komponen Keystore dan hubungannya.

AndroidKeystore adalah API Android Framework dan komponen yang digunakan oleh aplikasi untuk mengakses fungsi Keystore. Ini diimplementasikan sebagai ekstensi ke API Arsitektur Kriptografi Java standar, dan terdiri dari kode Java yang berjalan di ruang proses aplikasi itu sendiri. AndroidKeystore memenuhi permintaan aplikasi untuk perilaku Keystore dengan meneruskan mereka ke daemon keystore.

Keystore daemon adalah sistem daemon Android yang menyediakan akses ke semua fungsi Keystore melalui API Binder . Ini bertanggung jawab untuk menyimpan "gumpalan kunci", yang berisi materi kunci rahasia yang sebenarnya, dienkripsi sehingga Keystore dapat menyimpannya tetapi tidak menggunakan atau mengungkapkannya.

keymasterd adalah server HIDL yang menyediakan akses ke Keymaster TA. (Nama ini tidak standar dan untuk tujuan konseptual.)

Keymaster TA (aplikasi terpercaya) adalah perangkat lunak yang berjalan dalam konteks aman, paling sering di TrustZone pada ARM SoC, yang menyediakan semua operasi Keystore yang aman, memiliki akses ke bahan kunci baku, memvalidasi semua kondisi kontrol akses pada kunci , dll.

LockSettingsService adalah komponen sistem Android bertanggung jawab untuk otentikasi pengguna, baik kata sandi dan sidik jari. Ini bukan bagian dari Keystore, tetapi relevan karena banyak operasi kunci Keystore memerlukan otentikasi pengguna. LockSettingsService berinteraksi dengan Gatekeeper TA dan Fingerprint TA untuk mendapatkan token otentikasi, yang menyediakan untuk daemon keystore, dan yang pada akhirnya dikonsumsi oleh aplikasi Keymaster TA.

Gatekeeper TA (aplikasi terpercaya) adalah komponen lain berjalan dalam konteks aman, yang bertanggung jawab untuk otentikasi password pengguna dan menghasilkan otentikasi token digunakan untuk membuktikan kepada Keymaster TA bahwa otentikasi dilakukan untuk pengguna tertentu pada titik waktu tertentu.

Sidik Jari TA (aplikasi terpercaya) adalah komponen lain berjalan dalam konteks aman yang bertanggung jawab untuk otentikasi sidik jari pengguna dan menghasilkan otentikasi token digunakan untuk membuktikan kepada Keymaster TA bahwa otentikasi dilakukan untuk pengguna tertentu pada titik waktu tertentu.

Arsitektur

Android Keystore API dan Keymaster HAL yang mendasarinya menyediakan seperangkat primitif kriptografi dasar namun memadai untuk memungkinkan penerapan protokol menggunakan kunci yang didukung perangkat keras dan dikontrol akses.

Keymaster HAL adalah perpustakaan yang disediakan OEM dan dapat dimuat secara dinamis yang digunakan oleh layanan Keystore untuk menyediakan layanan kriptografi yang didukung perangkat keras. Untuk menjaga keamanan, implementasi HAL tidak melakukan operasi sensitif apa pun di ruang pengguna, atau bahkan di ruang kernel. Operasi sensitif didelegasikan ke prosesor aman yang dicapai melalui beberapa antarmuka kernel. Arsitektur yang dihasilkan terlihat seperti ini:

Akses ke Keymaster

Gambar 1. Akses ke Keymaster

Dalam perangkat Android, "klien" dari Keymaster HAL terdiri dari beberapa lapisan (misalnya aplikasi, kerangka kerja, daemon Keystore), tetapi itu dapat diabaikan untuk keperluan dokumen ini. Ini berarti bahwa Keymaster HAL API yang dijelaskan adalah level rendah, digunakan oleh komponen internal platform, dan tidak diekspos ke developer aplikasi. The-tingkat yang lebih tinggi API dijelaskan di situs Pengembang Android .

Tujuan dari Keymaster HAL bukan untuk mengimplementasikan algoritme yang sensitif terhadap keamanan tetapi hanya untuk mengatur dan menghapus permintaan ke dunia yang aman. Format kawat ditentukan oleh implementasi.

Kompatibilitas dengan versi sebelumnya

Keymaster 1 HAL sama sekali tidak kompatibel dengan HAL yang dirilis sebelumnya, misalnya Keymaster 0.2 dan 0.3. Untuk memfasilitasi interoperabilitas pada perangkat yang menjalankan Android 5.0 dan sebelumnya yang diluncurkan dengan Keymaster HALs yang lebih lama, Keystore menyediakan adaptor yang mengimplementasikan Keymaster 1 HAL dengan panggilan ke pustaka perangkat keras yang ada. Hasilnya tidak dapat menyediakan fungsionalitas lengkap di Keymaster 1 HAL. Secara khusus, ini hanya mendukung algoritme RSA dan ECDSA, dan semua penegakan otorisasi utama dilakukan oleh adaptor, di dunia yang tidak aman.

Keymaster 2 lebih menyederhanakan antarmuka HAL dengan menghapus get_supported_* metode dan memungkinkan finish() metode untuk menerima input. Ini mengurangi jumlah perjalanan pulang pergi ke TEE dalam kasus di mana input tersedia sekaligus, dan menyederhanakan implementasi dekripsi AEAD.

Di Android 8.0, Keymaster 3 bertransisi dari HAL struktur-C gaya lama ke antarmuka C++ HAL yang dihasilkan dari definisi di Hardware Interface Definition Language (HIDL) baru. Implementasi HAL gaya baru yang dibuat oleh subclassing yang dihasilkan IKeymasterDevice kelas dan menerapkan metode virtual murni. Sebagai bagian dari perubahan, banyak tipe argumen telah berubah, meskipun tipe dan metode memiliki korespondensi satu-ke-satu dengan tipe lama dan metode struct HAL.

Ikhtisar HIDL

Hardware Interface Definition Language (HIDL) menyediakan mekanisme implementasi bahasa-independen untuk menentukan antarmuka perangkat keras. Perkakas HIDL saat ini mendukung pembuatan antarmuka C++ dan Java. Diharapkan bahwa sebagian besar pelaksana Trusted Execution Environment (TEE) akan menemukan alat C++ lebih nyaman, sehingga dokumen ini hanya membahas representasi C++.

Antarmuka HIDL terdiri dari satu set metode, dinyatakan sebagai:

  methodName(INPUT ARGUMENTS) generates (RESULT ARGUMENTS);

Ada berbagai tipe yang telah ditentukan sebelumnya, dan HAL dapat menentukan tipe enumerasi dan struktur baru. Untuk rincian lebih lanjut tentang HIDL, lihat bagian Referensi .

Contoh metode dari Keymaster 3 IKeymasterDevice.hal adalah:

generateKey(vec<KeyParameter> keyParams)
        generates(ErrorCode error, vec<uint8_t> keyBlob,
                  KeyCharacteristics keyCharacteristics);

Ini setara dengan yang berikut dari keymaster2 HAL:

keymaster_error_t (*generate_key)(
        const struct keymaster2_device* dev,
        const keymaster_key_param_set_t* params,
        keymaster_key_blob_t* key_blob,
        keymaster_key_characteristics_t* characteristics);

Dalam versi HIDL, yang dev argumen dihapus, karena itu implisit. The params Argumen tidak lagi struct yang berisi pointer referensi array key_parameter_t objek, tetapi vec (vektor) yang mengandung KeyParameter benda. Kembali nilai-nilai yang tercantum dalam " generates " klausa, termasuk vektor uint8_t nilai untuk gumpalan kunci.

Metode virtual C++ yang dihasilkan oleh kompiler HIDL adalah:

Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
                         generateKey_cb _hidl_cb) override;

Di mana generate_cb adalah fungsi pointer didefinisikan sebagai:

std::function<void(ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
                   const KeyCharacteristics& keyCharacteristics)>

Artinya, generate_cb adalah fungsi yang mengambil kembali nilai-nilai yang tercantum dalam menghasilkan klausa. HAL kelas implementasi menimpa ini generateKey metode dan memanggil generate_cb fungsi pointer untuk mengembalikan hasil operasi ke pemanggil. Catatan panggilan fungsi pointer adalah sinkron. Penelepon panggilan generateKey dan generateKey memanggil fungsi pointer yang disediakan, yang mengeksekusi sampai selesai, kembali kontrol ke generateKey implementasi, yang kemudian kembali ke pemanggil.

Untuk contoh rinci, lihat implementasi standar di hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp . Implementasi default menyediakan kompatibilitas mundur untuk perangkat dengan keymaster0, keymaster1, atau keymaster2 HALS gaya lama.

Kontrol akses

Aturan paling dasar dari kontrol akses Keystore adalah bahwa setiap aplikasi memiliki namespace sendiri. Tetapi untuk setiap aturan ada pengecualian. Keystore memiliki beberapa peta berkode keras yang memungkinkan komponen sistem tertentu untuk mengakses ruang nama tertentu lainnya. Ini adalah instrumen yang sangat tumpul karena memberikan satu komponen kontrol penuh atas namespace lain. Dan kemudian ada soal komponen vendor sebagai klien ke Keystore. Saat ini kami tidak memiliki cara untuk membuat namespace untuk komponen vendor, misalnya, pemohon WPA.

Untuk mengakomodasi komponen vendor dan menggeneralisasi kontrol akses tanpa pengecualian hard-code, Keystore 2.0 memperkenalkan domain dan ruang nama SELinux.

Domain Toko Kunci

Dengan domain Keystore, kita dapat memisahkan ruang nama dari UID. Klien yang mengakses kunci di Keystore harus menentukan domain, namespace, dan alias yang ingin mereka akses. Berdasarkan tuple ini dan identitas pemanggil, kita dapat menentukan kunci mana yang ingin diakses pemanggil dan apakah kunci tersebut memiliki izin yang sesuai.

Kami memperkenalkan lima parameter domain yang mengatur bagaimana kunci dapat diakses. Mereka mengontrol semantik parameter namespace dari deskriptor kunci dan bagaimana kontrol akses dilakukan.

  • DOMAIN_APP : Domain aplikasi meliputi perilaku warisan. Java Keystore SPI menggunakan domain ini secara default. Ketika domain ini digunakan, argumen namespace diabaikan dan UID pemanggil digunakan sebagai gantinya. Akses ke domain ini dikendalikan oleh label Keystore ke kelas keystore_key dalam kebijakan SELinux.
  • DOMAIN_SELINUX : Domain ini menunjukkan bahwa namespace memiliki label dalam kebijakan SELinux. Parameter namespace mendongak dan diterjemahkan ke dalam konteks sasaran, dan cek izin dilakukan untuk konteks SELinux menyerukan keystore_key kelas. Ketika izin telah ditetapkan untuk operasi yang diberikan, tupel penuh digunakan untuk pencarian kunci.
  • DOMAIN_GRANT : Domain hibah menunjukkan bahwa parameter namespace adalah identifier hibah. Parameter alias diabaikan. Pemeriksaan SELinux dilakukan saat hibah dibuat. Kontrol akses lebih lanjut hanya memeriksa apakah UID pemanggil cocok dengan UID penerima hibah dari hibah yang diminta.
  • DOMAIN_KEY_ID : Domain ini menunjukkan bahwa parameter namespace adalah kunci id yang unik. Kunci itu sendiri mungkin telah dibuat dengan DOMAIN_APP atau DOMAIN_SELINUX . Cek izin dilakukan setelah domain dan namespace telah diambil dari database kunci dalam cara yang sama seperti jika gumpalan itu dimuat oleh domain, namespace, dan alias tupel. Alasan untuk domain id kunci adalah kontinuitas. Saat mengakses kunci dengan alias, panggilan berikutnya dapat beroperasi pada kunci yang berbeda, karena kunci baru mungkin telah dibuat atau diimpor dan diikat ke alias ini. ID kunci, bagaimanapun, tidak pernah berubah. Jadi ketika menggunakan key by key id setelah di-load dari database Keystore menggunakan alias satu kali, dapat dipastikan bahwa itu adalah key yang sama selama key id masih ada. Fungsionalitas ini tidak diekspos ke pengembang aplikasi. Sebaliknya, ini digunakan dalam Android Keystore SPI untuk memberikan pengalaman yang lebih konsisten bahkan ketika digunakan secara bersamaan dengan cara yang tidak aman.
  • DOMAIN_BLOB : Domain gumpalan menunjukkan bahwa si penelepon mengelola gumpalan dengan sendirinya. Ini digunakan untuk klien yang perlu mengakses Keystore sebelum partisi data dipasang. Gumpalan kunci termasuk dalam blob bidang descriptor kunci.

Menggunakan domain SELinux, kami dapat memberikan komponen vendor akses ke ruang nama Keystore yang sangat spesifik yang dapat digunakan bersama oleh komponen sistem seperti dialog pengaturan.

Kebijakan SELinux untuk keystore_key

Label namespace dikonfigurasi menggunakan keystore2_key_context berkas.
Setiap baris dalam file ini memetakan id namespace numerik ke label SELinux. Sebagai contoh,

# 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

Setelah menyiapkan ruang nama kunci baru dengan cara ini, kami dapat memberikan akses ke sana dengan menambahkan kebijakan yang sesuai. Misalnya, untuk memungkinkan wpa_supplicant untuk mendapatkan dan kunci digunakan dalam namespace baru kami akan menambahkan baris berikut ke hal_wifi_supplicant.te :

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

Setelah menyiapkan namespace baru, AndroidKeyStore dapat digunakan hampir seperti biasa. Satu-satunya perbedaan adalah bahwa ID namespace harus ditentukan. Untuk memuat dan mengimpor kunci dari dan ke Keystore, namespace id ditentukan menggunakan AndroidKeyStoreLoadStoreParameter . Sebagai contoh,

import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
import java.security.KeyStore;

KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
keystore.load(new AndroidKeyStoreLoadStoreParameter(102));

Untuk membuat kunci dalam namespace yang diberikan, namespace id harus diberikan menggunakan KeyGenParameterSpec.Builder#setNamespace():

import android.security.keystore.KeyGenParameterSpec;
KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder();
specBuilder.setNamespace(102);

File konteks berikut dapat digunakan untuk mengonfigurasi ruang nama Keystore 2.0 SELinux. Setiap partisi memiliki rentang yang berbeda dari 10.000 id namespace untuk menghindari tabrakan.

Partisi Jangkauan File konfigurasi
Sistem 0 ... 9.999
/system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Sistem yang Diperpanjang 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
Penjaja 30.000 ... 39.999
/vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Permintaan klien kunci dengan meminta domain SELinux dan namespace virtual yang diinginkan, dalam hal ini "wifi_key" , dengan id numerik.

Di atas itu, ruang nama berikut telah ditentukan. Jika mereka mengganti aturan khusus, tabel berikut menunjukkan UID yang mereka gunakan untuk berhubungan.

ID ruang nama Label Kebijakan SE UID Keterangan
0 su_key T/A Kunci pengguna super. Hanya digunakan untuk pengujian pada userdebug dan eng build. Tidak relevan pada build pengguna.
1 shell_key T/A Namespace tersedia untuk shell. Sebagian besar digunakan untuk pengujian, tetapi dapat digunakan pada build pengguna juga dari baris perintah.
100 vold_key T/A Ditujukan untuk digunakan oleh vold.
101 odsing_key T/A Digunakan oleh daemon penandatanganan pada perangkat.
102 wifi_key AID_WIFI(1010) Digunakan oleh sistem Wifi Android termasuk wpa_supplicant.
120 resume_on_reboot_key AID_SYSTEM(1000) Digunakan oleh server sistem Android untuk mendukung resume saat reboot.

Akses Vektor

Kelas SELinux keystore_key telah berusia cukup sedikit dan beberapa hak akses, seperti verify atau sign telah kehilangan maknanya. Berikut adalah set baru perizinan, keystore2_key , yang Keystore 2.0 akan menegakkan.

Izin Arti
delete Diperiksa saat melepas kunci dari Keystore.
get_info Diperiksa saat metadata kunci diminta.
grant Penelepon memerlukan izin ini untuk membuat hibah ke kunci dalam konteks target.
manage_blob Penelepon dapat menggunakan DOMAIN_BLOB pada namespace SELinux diberikan, sehingga pengelolaan gumpalan dengan sendirinya. Ini secara khusus berguna untuk vold.
rebind Izin ini mengontrol apakah alias dapat di-rebound ke kunci baru. Ini diperlukan untuk penyisipan dan menyiratkan bahwa kunci yang terikat sebelumnya akan dihapus. Ini pada dasarnya adalah izin penyisipan, tetapi menangkap semantik keystore dengan lebih baik.
req_forced_op Klien dengan izin ini dapat membuat operasi yang tidak dapat dipangkas, dan pembuatan operasi tidak pernah gagal kecuali semua slot operasi diambil oleh operasi yang tidak dapat dipangkas.
update Diperlukan untuk memperbarui subkomponen kunci.
use Diperiksa saat membuat operasi Keymint yang menggunakan materi kunci, misalnya untuk penandatanganan, en/dekripsi.
use_dev_id Diperlukan saat membuat informasi pengenal perangkat, seperti pengesahan id perangkat.

Selain itu, kami membagi satu set izin khusus keystore non kunci dalam SELinux kelas keamanan keystore2 :

Izin Arti
add_auth Diperlukan oleh penyedia autentikasi seperti Gatekeeper atau BiometricsManager untuk menambahkan token autentikasi.
clear_ns Sebelumnya clear_uid, izin ini memungkinkan yang bukan pemilik namespace untuk menghapus semua kunci di namespace tersebut.
list Diperlukan oleh sistem untuk menghitung kunci dengan berbagai properti, seperti kepemilikan atau batasan auth. Izin ini tidak diperlukan oleh penelepon yang menghitung ruang nama mereka sendiri. Ini ditutupi oleh get_info izin.
lock Izin ini memungkinkan untuk mengunci Keystore, yaitu, mengeluarkan kunci master, sehingga kunci terikat auth menjadi tidak dapat digunakan dan tidak dapat dibuat.
reset Izin ini memungkinkan untuk mengatur ulang Keystore ke default pabrik, menghapus semua kunci yang tidak penting untuk berfungsinya OS Android.
unlock Izin ini diperlukan untuk mencoba membuka kunci master untuk kunci terikat autentikasi.