Halaman ini berisi informasi tentang fitur kriptografi Android Keystore, sebagaimana disediakan oleh implementasi KeyMint (atau Keymaster) yang mendasarinya.
Primitif kriptografi
Keystore menyediakan kategori operasi berikut:
- Pembuatan kunci, yang menghasilkan materi kunci pribadi atau rahasia yang hanya dapat diakses oleh lingkungan yang aman. Klien dapat membuat kunci dengan cara
berikut:
- Pembuatan kunci baru
- Mengimpor materi kunci yang tidak dienkripsi
- Mengimpor materi kunci terenkripsi
- Pengesahan kunci: Pembuatan kunci asimetris menghasilkan sertifikat yang menyimpan bagian kunci publik dari pasangan kunci. Sertifikat ini juga dapat menyimpan informasi tentang metadata untuk kunci dan status perangkat, yang semuanya ditandatangani oleh pengaitan kunci kembali ke root tepercaya.
- Operasi kriptografi:
- Enkripsi dan dekripsi simetris (AES, 3DES)
- Dekripsi asimetris (RSA)
- Penandatanganan asimetris (ECDSA, RSA)
- Penandatanganan dan verifikasi simetris (HMAC)
- Perjanjian kunci asimetris (ECDH)
Perhatikan bahwa Keystore dan KeyMint tidak menangani operasi kunci publik untuk kunci asimetris.
Elemen protokol, seperti tujuan, mode, dan padding, serta batasan kontrol akses, ditentukan saat kunci dibuat atau diimpor dan terikat secara permanen ke kunci, sehingga memastikan kunci tidak dapat digunakan dengan cara lain.
Selain daftar di atas, ada satu lagi layanan yang disediakan oleh implementasi KeyMint (sebelumnya Keymaster), tetapi tidak diekspos sebagai API: Pembuatan angka acak. Hal ini digunakan secara internal untuk pembuatan kunci, Vektor Inisialisasi (IV), padding acak, dan elemen lain dari protokol aman yang memerlukan keacakan.
Primitif yang diperlukan
Semua implementasi KeyMint menyediakan:
- RSA
- Dukungan kunci 2048, 3072, dan 4096 bit
- Dukungan untuk eksponen publik F4 (2^16+1)
- Mode padding untuk penandatanganan RSA:
- RSASSA-PSS (
PaddingMode::RSA_PSS
) - RSASSA-PKCS1-v1_5 (
PaddingMode::RSA_PKCS1_1_5_SIGN
)
- RSASSA-PSS (
- Mode ringkasan untuk penandatanganan RSA:
- SHA-256
- Mode padding untuk enkripsi/dekripsi RSA:
- Tanpa bantalan
- RSAES-OAEP (
PaddingMode::RSA_OAEP
) - RSAES-PKCS1-v1_5 (
PaddingMode::RSA_PKCS1_1_5_ENCRYPT
)
- ECDSA
- Dukungan kunci 224, 256, 384, dan 521-bit didukung, menggunakan kurva NIST P-224, P-256, P-384, dan P-521.
- Mode ringkasan untuk ECDSA:
- Tidak ada ringkasan (tidak digunakan lagi, akan dihapus pada masa mendatang)
- SHA-256
- AES
- Kunci 128 dan 256 bit didukung
- CBC, CTR, ECB, dan GCM. Implementasi GCM tidak mengizinkan penggunaan tag yang lebih kecil dari 96 bit atau panjang nonce selain 96 bit.
- Mode padding
PaddingMode::NONE
danPaddingMode::PKCS7
didukung untuk mode CBC dan ECB. Tanpa padding, enkripsi mode CBC atau ECB akan gagal jika input bukan kelipatan ukuran blok.
- HMAC SHA-256, dengan ukuran kunci apa pun hingga minimal 32 byte.
SHA1 dan anggota keluarga SHA2 lainnya (SHA-224, SHA384, dan SHA512) sangat direkomendasikan untuk penerapan KeyMint. Keystore menyediakannya dalam software jika implementasi KeyMint hardware tidak menyediakannya.
Beberapa primitif juga direkomendasikan untuk interoperabilitas dengan sistem lain:
- Ukuran kunci yang lebih kecil untuk RSA
- Eksponen publik arbitrer untuk RSA
Kontrol akses kunci
Kunci berbasis hardware yang tidak pernah dapat diekstrak dari perangkat tidak memberikan banyak keamanan jika penyerang dapat menggunakannya sesuka hati (meskipun lebih aman daripada kunci yang dapat diekstraksi). Oleh karena itu, sangat penting agar Keystore menerapkan kontrol akses.
Kontrol akses ditentukan sebagai "daftar otorisasi" pasangan tag/nilai. Tag otorisasi adalah bilangan bulat 32-bit dan nilainya adalah berbagai jenis. Beberapa tag dapat diulang untuk menentukan beberapa nilai. Apakah tag dapat diulang ditentukan dalam antarmuka HAL KeyMint. Saat kunci dibuat, pemanggil menentukan daftar otorisasi. Implementasi KeyMint yang mendasari Keystore mengubah daftar untuk menentukan beberapa informasi tambahan, seperti apakah kunci memiliki perlindungan rollback, dan menampilkan daftar otorisasi "final", yang dienkode ke dalam blob kunci yang ditampilkan. Setiap upaya untuk menggunakan kunci untuk operasi kriptografi apa pun akan gagal jika daftar otorisasi akhir diubah.
Untuk Keymaster 2 dan yang lebih lama, kumpulan kemungkinan tag
ditentukan dalam enumerasi
keymaster_authorization_tag_t
dan
ditetapkan secara permanen (meskipun dapat diperluas).
Nama diawali dengan KM_TAG
. Empat bit teratas ID tag digunakan untuk menunjukkan jenis.
Keymaster 3 mengubah awalan KM_TAG
menjadi
Tag::
.
Jenis yang memungkinkan mencakup:
ENUM
: Nilai banyak tag ditentukan dalam
enumerasi. Misalnya, kemungkinan nilai TAG::PURPOSE
ditentukan dalam enum keymaster_purpose_t
.
ENUM_REP
: Sama seperti ENUM
,
kecuali tag dapat diulang dalam daftar otorisasi. Pengulangan
menunjukkan beberapa nilai yang diizinkan. Misalnya, kunci enkripsi
kemungkinan memiliki KeyPurpose::ENCRYPT
dan
KeyPurpose::DECRYPT
.
Saat KeyMint membuat kunci, pemanggil menentukan daftar otorisasi untuk kunci. Daftar ini diubah oleh Keystore dan KeyMint untuk menambahkan batasan tambahan, dan implementasi KeyMint yang mendasarinya mengenkode daftar otorisasi akhir ke dalam keyblob yang ditampilkan. Daftar otorisasi yang dienkode terikat secara kriptografis ke dalam keyblob, sehingga setiap upaya untuk mengubah daftar otorisasi (termasuk pengurutan) akan menghasilkan keyblob yang tidak valid dan tidak dapat digunakan untuk operasi kriptografi.
Penegakan kebijakan hardware versus software
Tidak semua implementasi hardware yang aman berisi fitur yang sama. Untuk mendukung berbagai pendekatan, Keymaster membedakan antara penegakan kontrol akses dunia yang aman dan tidak aman, atau penegakan hardware dan software.
Hal ini diekspos di KeyMint API dengan kolom securityLevel
dari
jenis KeyCharacteristics
. Hardware aman bertanggung jawab untuk menempatkan otorisasi di
KeyCharacteristics
dengan tingkat keamanan yang sesuai, berdasarkan apa yang dapat
diterapkannya. Informasi ini juga ditampilkan dalam
catatan pengesahan untuk kunci asimetris: karakteristik kunci
untuk SecurityLevel::TRUSTED_ENVIRONMENT
atau SecurityLevel::STRONGBOX
muncul dalam
daftar hardwareEnforced
, dan karakteristik
untuk SecurityLevel::SOFTWARE
atau
SecurityLevel::KEYSTORE
muncul dalam
daftar softwareEnforced
.
Misalnya, batasan pada interval tanggal dan waktu saat kunci dapat digunakan biasanya tidak diterapkan oleh lingkungan yang aman, karena lingkungan tersebut tidak memiliki akses yang tepercaya ke informasi tanggal dan waktu. Akibatnya, otorisasi seperti
Tag::ORIGINATION_EXPIRE_DATETIME
diberlakukan oleh Keystore di
Android, dan akan memiliki SecurityLevel::KEYSTORE
.
Untuk mengetahui informasi selengkapnya tentang cara menentukan apakah kunci dan otorisasinya didukung hardware, lihat Pengesahan kunci.
Otorisasi pembuatan pesan kriptografi
Tag berikut digunakan untuk menentukan karakteristik kriptografi operasi menggunakan kunci terkait:
Tag::ALGORITHM
Tag::KEY_SIZE
Tag::BLOCK_MODE
Tag::PADDING
Tag::CALLER_NONCE
Tag::DIGEST
Tag::MGF_DIGEST
Tag berikut dapat diulang, yang berarti beberapa nilai dapat dikaitkan dengan satu kunci:
Tag::BLOCK_MODE
Tag::PADDING
Tag::DIGEST
Tag::MGF_DIGEST
Nilai yang akan digunakan ditentukan pada waktu operasi.
Tujuan
Kunci memiliki serangkaian tujuan terkait, yang dinyatakan sebagai satu atau beberapa entri otorisasi dengan tag Tag::PURPOSE
, yang menentukan cara penggunaannya. Tujuannya ditentukan dalam
KeyPurpose.aidl
.
Perhatikan bahwa beberapa kombinasi nilai tujuan menimbulkan masalah keamanan. Misalnya, kunci RSA yang dapat digunakan untuk mengenkripsi dan menandatangani memungkinkan penyerang yang dapat meyakinkan sistem untuk mendekripsi data arbitrer guna menghasilkan tanda tangan.
Impor kunci
Keymaster hanya mendukung ekspor kunci publik, dalam format X.509, dan impor:
- Pasangan kunci asimetris dalam format PKCS#8 berenkode DER (tanpa enkripsi berbasis sandi)
- Kunci simetris sebagai byte mentah
Untuk memastikan bahwa kunci yang diimpor dapat dibedakan dari kunci yang dibuat secara aman, Tag::ORIGIN
disertakan dalam daftar otorisasi kunci yang sesuai. Misalnya, jika kunci dibuat di hardware yang aman, Tag::ORIGIN
dengan nilai KeyOrigin::GENERATED
ditemukan dalam daftar hw_enforced
karakteristik kunci, sedangkan kunci yang diimpor ke hardware yang aman memiliki nilai KeyOrigin::IMPORTED
.
Autentikasi pengguna
Implementasi KeyMint yang aman tidak menerapkan autentikasi pengguna, tetapi bergantung pada aplikasi tepercaya lainnya yang melakukannya. Untuk antarmuka yang diimplementasikan aplikasi ini, lihat halaman Gatekeeper.
Persyaratan autentikasi pengguna ditentukan melalui dua set tag. Set pertama menunjukkan metode autentikasi mana yang mengizinkan penggunaan kunci:
Tag::USER_SECURE_ID
memiliki nilai numerik 64-bit yang menentukan ID pengguna aman yang diberikan dalam token autentikasi aman untuk membuka kunci penggunaan kunci. Jika diulang, kunci dapat digunakan jika salah satu nilai diberikan dalam token autentikasi yang aman.
Set kedua menunjukkan apakah dan kapan pengguna perlu diautentikasi.
Jika tidak ada tag ini, tetapi ada Tag::USER_SECURE_ID
, autentikasi diperlukan untuk setiap penggunaan kunci.
Tag::NO_AUTHENTICATION_REQUIRED
menunjukkan bahwa tidak ada autentikasi pengguna yang diperlukan, meskipun akses ke kunci masih dibatasi untuk aplikasi pemilik (dan aplikasi apa pun yang diberi akses).Tag::AUTH_TIMEOUT
adalah nilai numerik yang menentukan, dalam detik, seberapa baru autentikasi pengguna harus dilakukan untuk mengizinkan penggunaan kunci. Waktu tunggu tidak melewati proses mulai ulang; setelah mulai ulang, semua autentikasi menjadi tidak valid. Waktu tunggu dapat disetel ke nilai yang besar untuk menunjukkan bahwa autentikasi diperlukan sekali per booting (2^32 detik adalah ~136 tahun; kemungkinan perangkat Android di-reboot lebih sering dari itu).
Memerlukan perangkat yang tidak terkunci
Kunci dengan Tag::UNLOCKED_DEVICE_REQUIRED
hanya dapat digunakan saat
perangkat tidak terkunci. Untuk semantik mendetail, lihat
KeyProtection.Builder#setUnlockedDeviceRequired(boolean)
.
UNLOCKED_DEVICE_REQUIRED
diterapkan oleh Keystore, bukan oleh
KeyMint. Namun, di Android 12 dan yang lebih tinggi, Keystore melindungi UNLOCKED_DEVICE_REQUIRED
kunci secara kriptografis saat perangkat terkunci
untuk memastikan bahwa, dalam sebagian besar kasus, kunci tidak dapat digunakan meskipun Keystore
terkompromi saat perangkat terkunci.
Untuk mencapai hal ini, Keystore "mengenkripsi super" semua kunci UNLOCKED_DEVICE_REQUIRED
sebelum menyimpannya di databasenya, dan jika memungkinkan, Keystore melindungi kunci enkripsi super (kunci super) saat perangkat terkunci sedemikian rupa sehingga kunci tersebut hanya dapat dipulihkan dengan keberhasilan membuka kunci perangkat. (Istilah "superenkripsi" digunakan karena lapisan enkripsi ini diterapkan selain lapisan enkripsi yang sudah diterapkan KeyMint ke semua kunci.)
Setiap pengguna (termasuk profil)
memiliki dua kunci super yang terkait dengan UNLOCKED_DEVICE_REQUIRED
:
- Kunci super simetris UnlockedDeviceRequired. Ini adalah kunci
AES‑256‑GCM. Fitur ini mengenkripsi
kunci
UNLOCKED_DEVICE_REQUIRED
yang diimpor atau dibuat saat perangkat tidak terkunci untuk pengguna. - Kunci super asimetris UnlockedDeviceRequired. Ini adalah pasangan kunci ECDH
P-521. Fitur ini mengenkripsi kunci
UNLOCKED_DEVICE_REQUIRED
yang diimpor atau dibuat saat perangkat dikunci untuk pengguna. Kunci yang dienkripsi dengan kunci asimetris ini akan dienkripsi ulang dengan kunci simetris saat pertama kali digunakan (yang hanya dapat terjadi saat perangkat tidak terkunci).
Keystore membuat kunci super ini pada saat pembuatan pengguna dan menyimpannya di database-nya, yang dienkripsi dengan sandi sintetis pengguna. Hal ini memungkinkan pemulihan menggunakan PIN, pola, atau sandi yang setara.
Keystore juga meng-cache kunci super ini dalam memori, sehingga dapat beroperasi pada kunci UNLOCKED_DEVICE_REQUIRED
. Namun, aplikasi ini mencoba menyimpan dalam cache bagian rahasia dari kunci ini hanya saat perangkat tidak terkunci untuk pengguna. Jika
perangkat dikunci untuk pengguna, Keystore akan mengosongkan salinan bagian rahasia yang di-cache dari kunci super ini, jika memungkinkan. Secara khusus, saat perangkat dikunci untuk pengguna, Keystore memilih dan menerapkan salah satu dari tiga tingkat perlindungan untuk kunci super UnlockedDeviceRequired pengguna:
- Jika pengguna hanya mengaktifkan PIN, pola, atau sandi, Keystore akan menghapus bagian rahasia dari kunci super yang di-cache. Hal ini membuat kunci super hanya dapat dipulihkan melalui salinan terenkripsi dalam database yang hanya dapat didekripsi dengan PIN, pola, atau sandi yang setara.
- Jika pengguna hanya mengaktifkan biometrik kelas 3 ("kuat") dan PIN, pola, atau sandi, maka Keystore akan mengatur agar kunci super dapat dipulihkan oleh salah satu biometrik kelas 3 yang terdaftar milik pengguna (biasanya sidik jari), sebagai alternatif yang setara dengan PIN, pola, atau sandi. Untuk melakukannya, aplikasi akan membuat kunci AES‑256‑GCM baru, mengenkripsi bagian rahasia kunci super dengannya, mengimpor kunci AES‑256‑GCM ke KeyMint sebagai kunci terikat biometrik yang memerlukan autentikasi biometrik agar berhasil dalam 15 detik terakhir, dan menghapus salinan teks biasa dari semua kunci ini.
- Jika pengguna mengaktifkan biometrik kelas 1 ("kenyamanan"), biometrik kelas 2 ("lemah"), atau agen kepercayaan buka kunci aktif, Keystore akan menyimpan kunci super yang di-cache dalam teks biasa. Dalam hal ini, keamanan kriptografi untuk kunci
UNLOCKED_DEVICE_REQUIRED
tidak disediakan. Pengguna dapat menghindari penggantian yang kurang aman ini dengan tidak mengaktifkan metode buka kunci ini. Metode buka kunci yang paling umum yang termasuk dalam kategori ini adalah buka kunci dengan wajah di banyak perangkat, dan buka kunci dengan smartwatch yang disambungkan.
Saat perangkat dibuka kuncinya untuk pengguna, Keystore akan memulihkan kunci super UnlockedDeviceRequired pengguna jika memungkinkan. Untuk membuka kunci yang setara dengan PIN, pola, atau sandi, kunci ini mendekripsi salinan kunci yang disimpan dalam database. Jika tidak, aplikasi akan memeriksa apakah aplikasi menyimpan salinan kunci ini yang dienkripsi dengan kunci terikat biometrik, dan jika ya, aplikasi akan mencoba mendekripsinya. Hal ini hanya berhasil jika pengguna telah berhasil diautentikasi dengan biometrik kelas 3 dalam 15 detik terakhir, yang diterapkan oleh KeyMint (bukan Keystore).
Binding klien
Pengikatan klien, yaitu pengaitan kunci dengan aplikasi klien tertentu, dilakukan melalui ID klien opsional dan beberapa data klien opsional (Tag::APPLICATION_ID
dan Tag::APPLICATION_DATA
). Keystore memperlakukan nilai ini sebagai blob buram, hanya memastikan bahwa blob yang sama yang ditampilkan selama pembuatan/impor kunci ditampilkan untuk setiap penggunaan dan identik byte demi byte. Data pengikatan klien tidak ditampilkan oleh
KeyMint. Pemanggil harus mengetahuinya untuk menggunakan kunci.
Fitur ini tidak diekspos ke aplikasi.
Masa berlaku
Keystore mendukung pembatasan penggunaan kunci menurut tanggal. Awal validitas kunci dan
masa berlaku kunci dapat dikaitkan dengan kunci dan Keymaster menolak untuk
melakukan operasi kunci jika tanggal/waktu saat ini berada di luar rentang
yang valid. Rentang validitas kunci ditentukan dengan tag
Tag::ACTIVE_DATETIME
,
Tag::ORIGINATION_EXPIRE_DATETIME
, dan
Tag::USAGE_EXPIRE_DATETIME
. Perbedaan antara
"asal" dan "penggunaan" didasarkan pada apakah kunci digunakan untuk
"membuat" ciphertext/tanda tangan/dll. baru, atau untuk "menggunakan"
ciphertext/tanda tangan/dll. yang ada. Perhatikan bahwa perbedaan ini tidak diekspos ke
aplikasi.
Tag Tag::ACTIVE_DATETIME
,
Tag::ORIGINATION_EXPIRE_DATETIME
,
dan Tag::USAGE_EXPIRE_DATETIME
bersifat opsional. Jika tag tidak ada, diasumsikan bahwa kunci yang dimaksud selalu dapat digunakan untuk mendekripsi/memverifikasi pesan.
Karena waktu jam dinding disediakan oleh dunia yang tidak aman, tag terkait masa berlaku ada dalam daftar yang diterapkan software.
Pengikatan root of trust
Keystore mengharuskan kunci diikat ke root of trust, yang merupakan string bit yang diberikan ke hardware aman KeyMint selama startup, sebaiknya oleh bootloader. String bit ini terikat secara kriptografis ke setiap kunci yang dikelola oleh KeyMint.
Root of trust terdiri dari kunci publik yang digunakan untuk memverifikasi tanda tangan pada image booting dan status kunci perangkat. Jika kunci publik diubah untuk mengizinkan penggunaan image sistem yang berbeda atau jika status kunci diubah, maka tidak ada kunci yang dilindungi KeyMint yang dibuat oleh sistem sebelumnya yang dapat digunakan, kecuali jika root tepercaya sebelumnya dipulihkan dan sistem yang ditandatangani oleh kunci tersebut di-boot. Tujuannya adalah untuk meningkatkan nilai kontrol akses kunci yang diterapkan software dengan membuat sistem operasi yang diinstal penyerang tidak dapat menggunakan kunci KeyMint.
Tombol mandiri
Beberapa hardware aman KeyMint dapat memilih untuk menyimpan materi kunci secara internal dan menampilkan handle, bukan materi kunci yang dienkripsi. Atau mungkin ada kasus lain saat kunci tidak dapat digunakan hingga komponen sistem dunia yang tidak aman atau aman lainnya tersedia. HAL KeyMint memungkinkan pemanggil meminta agar kunci menjadi "mandiri", melalui tag TAG::STANDALONE
, yang berarti tidak ada resource selain blob dan sistem KeyMint yang sedang berjalan yang diperlukan. Tag yang terkait dengan kunci dapat diperiksa untuk melihat apakah kunci
bersifat mandiri. Saat ini, hanya dua nilai yang ditentukan:
KeyBlobUsageRequirements::STANDALONE
KeyBlobUsageRequirements::REQUIRES_FILE_SYSTEM
Fitur ini tidak diekspos ke aplikasi.
Kecepatan
Saat dibuat, kecepatan penggunaan maksimum dapat ditentukan dengan TAG::MIN_SECONDS_BETWEEN_OPS
.
Implementasi TrustZone menolak untuk melakukan operasi kriptografi
dengan kunci tersebut jika operasi dilakukan kurang
dari TAG::MIN_SECONDS_BETWEEN_OPS
detik sebelumnya.
Pendekatan sederhana untuk menerapkan batas kecepatan adalah tabel ID kunci dan stempel waktu penggunaan terakhir. Tabel ini memiliki ukuran terbatas, tetapi dapat menampung setidaknya 16 entri. Jika tabel penuh dan tidak ada entri yang dapat diperbarui atau dihapus, implementasi hardware yang aman akan "gagal aman", lebih memilih untuk menolak semua operasi kunci yang dibatasi kecepatan hingga salah satu entri berakhir. Semua entri dapat berakhir masa berlakunya saat perangkat dimulai ulang.
Kunci juga dapat dibatasi hingga n penggunaan per booting dengan
TAG::MAX_USES_PER_BOOT
. Hal ini juga memerlukan tabel pelacakan, yang menampung minimal empat kunci dan juga gagal aman. Perhatikan bahwa aplikasi tidak dapat membuat kunci terbatas per-boot. Fitur ini tidak diekspos melalui Keystore dan dicadangkan untuk operasi sistem.
Fitur ini tidak diekspos ke aplikasi.
Pengisian ulang generator angka acak
Karena hardware yang aman menghasilkan angka acak untuk materi kunci dan vektor inisialisasi (IV), dan karena generator angka acak hardware mungkin tidak selalu sepenuhnya dapat dipercaya, HAL KeyMint menyediakan antarmuka untuk memungkinkan klien memberikan entropi tambahan, yang dicampur ke dalam angka acak yang dihasilkan.
Gunakan generator angka acak hardware sebagai sumber nilai awal utama. Data awal yang disediakan melalui API eksternal tidak dapat menjadi satu-satunya sumber keacakan yang digunakan untuk pembuatan angka. Selain itu, operasi pencampuran yang digunakan harus memastikan bahwa output acak tidak dapat diprediksi jika salah satu sumber nilai awal tidak dapat diprediksi.