Seperti sebagian besar software enkripsi disk dan file, enkripsi penyimpanan Android secara tradisional mengandalkan kunci enkripsi mentah yang ada di memori sistem sehingga enkripsi dapat dilakukan. Meskipun enkripsi dilakukan oleh hardware khusus, bukan oleh software, software umumnya masih perlu mengelola kunci enkripsi mentah.
Hal ini biasanya tidak dianggap sebagai masalah karena kunci tidak akan ada selama serangan offline, yang merupakan jenis serangan utama yang ingin dilindungi oleh enkripsi penyimpanan. Namun, ada keinginan untuk memberikan peningkatan perlindungan terhadap jenis serangan lainnya, seperti serangan cold boot, dan serangan online yang memungkinkan penyerang membocorkan memori sistem tanpa membahayakan perangkat sepenuhnya.
Untuk mengatasi masalah ini, Android 11 memperkenalkan dukungan untuk tombol yang digabungkan dengan hardware, yang dilengkapi dukungan hardware. Kunci yang digabungkan dengan hardware adalah kunci penyimpanan yang hanya diketahui dalam bentuk mentah untuk hardware khusus; software hanya melihat dan menggunakan kunci ini dalam bentuk digabungkan (dienkripsi). Hardware ini harus dapat membuat dan mengimpor kunci penyimpanan, menggabungkan kunci penyimpanan dalam bentuk sementara dan jangka panjang, memperoleh subkunci, memprogram satu subkunci secara langsung ke dalam mesin kripto inline, dan menampilkan subkunci terpisah ke software.
Catatan: Inline crypto engine (atau inline encryption hardware) mengacu pada hardware yang mengenkripsi/mendekode data saat data sedang dalam perjalanan ke/dari perangkat penyimpanan. Biasanya ini adalah pengontrol host UFS atau eMMC yang mengimplementasikan ekstensi kripto yang ditentukan oleh spesifikasi JEDEC yang sesuai.
Desain
Bagian ini menyajikan desain fitur kunci yang digabungkan dengan hardware, termasuk dukungan hardware yang diperlukan untuk fitur tersebut. Diskusi ini berfokus pada enkripsi berbasis file (FBE), tetapi solusi ini juga berlaku untuk enkripsi metadata.
Salah satu cara untuk menghindari kebutuhan kunci enkripsi mentah di memori sistem adalah dengan menyimpan kunci tersebut hanya di slot kunci mesin kripto inline. Namun, pendekatan ini mengalami beberapa masalah:
- Jumlah kunci enkripsi mungkin melebihi jumlah slot kunci.
- Mesin kripto inline biasanya kehilangan isi slot kunci jika pengontrol penyimpanan (biasanya UFS atau eMMC) direset. Mereset pengontrol penyimpanan adalah prosedur pemulihan error standar yang dijalankan jika terjadi jenis error penyimpanan tertentu, dan error tersebut dapat terjadi kapan saja. Oleh karena itu, saat kripto inline digunakan, sistem operasi harus selalu siap untuk memprogram ulang slot kunci tanpa intervensi pengguna.
- Mesin kripto inline hanya dapat digunakan untuk mengenkripsi/mendekripsi blok data penuh di disk. Namun, dalam kasus FBE, software masih harus dapat melakukan tugas kriptografis lainnya seperti enkripsi nama file dan mendapatkan ID kunci. Software masih memerlukan akses ke kunci FBE mentah untuk melakukan pekerjaan lain ini.
Untuk menghindari masalah ini, kunci penyimpanan dibuat menjadi kunci yang digabungkan dengan hardware, yang hanya dapat dibuka lapisannya dan digunakan oleh hardware khusus. Dengan begitu, jumlah kunci yang didukung tidak terbatas. Selain itu, hierarki kunci diubah dan sebagian dipindahkan ke hardware ini, yang memungkinkan subkunci ditampilkan ke software untuk tugas yang tidak dapat menggunakan mesin kripto inline.
Hierarki kunci
Kunci dapat berasal dari kunci lain menggunakan KDF (fungsi turunan kunci) seperti HKDF, sehingga menghasilkan hierarki kunci.
Diagram berikut menggambarkan hierarki kunci umum untuk FBE saat kunci yang digabungkan dengan hardware tidak digunakan:
Kunci class FBE adalah kunci enkripsi mentah yang diteruskan Android ke kernel Linux untuk membuka kunci kumpulan direktori terenkripsi tertentu, seperti penyimpanan terenkripsi kredensial untuk pengguna Android tertentu. (Di kernel, kunci ini disebut kunci master fscrypt.) Dari kunci ini, kernel memperoleh subkunci berikut:
- ID kunci. Ini tidak digunakan untuk enkripsi, tetapi merupakan nilai yang digunakan untuk mengidentifikasi kunci yang digunakan untuk melindungi file atau direktori tertentu.
- Kunci enkripsi isi file
- Kunci enkripsi nama file
Sebaliknya, diagram berikut menggambarkan hierarki kunci untuk FBE saat kunci yang digabungkan dengan hardware digunakan:
Dibandingkan dengan kasus sebelumnya, tingkat tambahan telah ditambahkan ke hierarki kunci, dan kunci enkripsi konten file telah dipindahkan. Node root masih mewakili kunci yang diteruskan Android ke Linux untuk membuka kunci kumpulan direktori terenkripsi. Namun, sekarang kunci tersebut dalam bentuk yang digabungkan secara singkat, dan agar dapat digunakan, kunci tersebut harus diteruskan ke hardware khusus. Hardware ini harus mengimplementasikan dua antarmuka yang menggunakan kunci yang digabungkan secara sementara:
- Satu antarmuka untuk mendapatkan
inline_encryption_key
dan langsung memprogramnya ke dalam slot kunci mesin crypto inline. Hal ini memungkinkan konten file dienkripsi/didekripsi tanpa software yang memiliki akses ke kunci mentah. Dalam kernel umum Android, antarmuka ini berkaitan dengan operasiblk_crypto_ll_ops::keyslot_program
, yang harus diimplementasikan oleh driver penyimpanan. - Satu antarmuka untuk mendapatkan dan menampilkan
sw_secret
("rahasia software" -- juga disebut "rahasia mentah" di beberapa tempat), yang merupakan kunci yang digunakan Linux untuk memperoleh subkunci untuk semua hal selain enkripsi konten file. Dalam kernel umum Android, antarmuka ini sesuai dengan operasiblk_crypto_ll_ops::derive_sw_secret
, yang harus diterapkan oleh driver penyimpanan.
Untuk mendapatkan inline_encryption_key
dan sw_secret
dari
kunci penyimpanan mentah, hardware harus menggunakan KDF yang kuat secara kriptografis. KDF ini
harus mengikuti praktik terbaik kriptografi; KDF harus memiliki kekuatan keamanan setidaknya
256 bit, yaitu cukup untuk algoritma apa pun yang digunakan nanti. Kunci ini juga harus menggunakan
label, konteks, dan string informasi khusus aplikasi yang berbeda saat
mengambil setiap jenis subkunci untuk menjamin bahwa sub-kunci yang dihasilkan
diisolasi secara kriptografis, yaitu, pengetahuan tentang salah satunya tidak mengungkapkan
subkunci lainnya. Pembentangan kunci tidak diperlukan, karena kunci penyimpanan mentah sudah merupakan
kunci acak yang seragam.
Secara teknis, KDF apa pun yang memenuhi persyaratan keamanan dapat digunakan.
Namun, untuk tujuan pengujian, Anda harus menerapkan kembali KDF yang sama dalam
kode pengujian. Saat ini, satu KDF telah ditinjau dan diterapkan; KDF ini dapat ditemukan
dalam kode sumber untuk vts_kernel_encryption_test
.
Sebaiknya hardware menggunakan KDF ini, yang menggunakan NIST SP 800-108 "KDF in Counter Mode" dengan AES-256-CMAC sebagai PRF. Perhatikan bahwa agar kompatibel, semua
bagian algoritma harus identik, termasuk pilihan konteks
dan label KDF untuk setiap subkunci.
Penggabungan kunci
Untuk memenuhi sasaran keamanan kunci yang digabungkan dengan hardware, dua jenis penggabungan kunci ditentukan:
- Penggabungan sementara: hardware mengenkripsi kunci mentah menggunakan kunci yang dibuat secara acak pada setiap booting dan tidak diekspos secara langsung di luar hardware.
- Penggabungan jangka panjang: hardware mengenkripsi kunci mentah menggunakan kunci unik dan persisten yang terintegrasi dalam hardware yang tidak langsung diekspos di luar hardware.
Semua kunci yang diteruskan ke kernel Linux untuk membuka kunci penyimpanan dibungkus secara sementara. Hal ini memastikan bahwa jika penyerang dapat mengekstrak kunci yang sedang digunakan dari memori sistem, kunci tersebut tidak hanya tidak dapat digunakan di luar perangkat, tetapi juga di perangkat setelah reboot.
Pada saat yang sama, Android masih harus dapat menyimpan versi terenkripsi kunci di disk sehingga kunci tersebut dapat dibuka kuncinya. Kunci mentah akan berfungsi untuk tujuan ini. Namun, sebaiknya jangan pernah menyimpan kunci mentah di memori sistem sehingga kunci tersebut tidak dapat diekstrak untuk digunakan di luar perangkat, meskipun diekstrak pada waktu booting. Karena alasan ini, konsep penggabungan jangka panjang telah ditentukan.
Untuk mendukung pengelolaan kunci yang digabungkan dengan dua cara yang berbeda ini, hardware harus menerapkan antarmuka berikut:
- Antarmuka untuk membuat dan mengimpor kunci penyimpanan, yang menampilkannya dalam
bentuk gabungan jangka panjang. Antarmuka ini diakses secara tidak langsung melalui KeyMint, dan sesuai dengan tag KeyMint
TAG_STORAGE_KEY
. Kemampuan "generate" digunakan olehvold
untuk membuat kunci penyimpanan baru yang akan digunakan oleh Android, sedangkan kemampuan "import" digunakan olehvts_kernel_encryption_test
untuk mengimpor kunci pengujian. - Antarmuka untuk mengonversi kunci penyimpanan gabungan jangka panjang menjadi
kunci penyimpanan gabungan sementara. Ini sesuai dengan
metode KeyMint
convertStorageKeyToEphemeral
. Metode ini digunakan olehvold
danvts_kernel_encryption_test
untuk membuka kunci penyimpanan.
Algoritma penggabungan kunci adalah detail implementasi, tetapi harus menggunakan AEAD yang kuat seperti AES-256-GCM dengan IV acak.
Diperlukan perubahan software
AOSP sudah memiliki framework dasar untuk mendukung kunci yang digabungkan dengan hardware. Ini
mencakup dukungan dalam komponen userspace seperti vold
, serta
dukungan kernel Linux di blk-crypto, fscrypt, dan
dm-default-key.
Namun, beberapa perubahan khusus implementasi diperlukan.
Perubahan KeyMint
Penerapan KeyMint perangkat harus diubah untuk mendukung
TAG_STORAGE_KEY
dan menerapkan
metode convertStorageKeyToEphemeral
.
Di Keymaster, exportKey
digunakan, bukan
convertStorageKeyToEphemeral
.
Perubahan kernel Linux
Driver kernel Linux untuk mesin kripto inline perangkat harus diubah untuk mendukung kunci yang digabungkan dengan hardware.
Untuk android14
dan kernel yang lebih tinggi,
tetapkan BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
dalam blk_crypto_profile::key_types_supported
,
buat blk_crypto_ll_ops::keyslot_program
dan blk_crypto_ll_ops::keyslot_evict
mendukung pemrograman/menghapus kunci yang digabungkan dengan hardware,
dan mengimplementasikan blk_crypto_ll_ops::derive_sw_secret
.
Untuk kernel android12
dan android13
,
setel BLK_CRYPTO_FEATURE_WRAPPED_KEYS
di blk_keyslot_manager::features
,
buat blk_ksm_ll_ops::keyslot_program
dan blk_ksm_ll_ops::keyslot_evict
mendukung pemrograman/penghapusan kunci yang digabungkan dengan hardware,
dan terapkan blk_ksm_ll_ops::derive_raw_secret
.
Untuk kernel android11
,
tetapkan BLK_CRYPTO_FEATURE_WRAPPED_KEYS
di keyslot_manager::features
,
buat keyslot_mgmt_ll_ops::keyslot_program
dan keyslot_mgmt_ll_ops::keyslot_evict
mendukung pemrograman/penghapusan kunci yang digabungkan dengan hardware,
dan terapkan keyslot_mgmt_ll_ops::derive_raw_secret
.
Pengujian
Meskipun enkripsi dengan kunci yang digabungkan dengan hardware lebih sulit diuji daripada enkripsi
dengan kunci standar, enkripsi ini masih dapat diuji dengan mengimpor kunci pengujian dan
menerapkan kembali derivasi kunci yang dilakukan hardware. Hal ini diterapkan
di vts_kernel_encryption_test
. Untuk menjalankan pengujian ini, jalankan:
atest -v vts_kernel_encryption_test
Baca log pengujian dan pastikan bahwa kasus pengujian utama yang digabungkan dengan hardware (misalnya,
FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
dan
DmDefaultKeyTest.TestHwWrappedKey
) tidak dilewati karena dukungan
untuk kunci yang digabungkan dengan hardware tidak terdeteksi, karena hasil pengujian masih
"diteruskan" dalam kasus tersebut.
Aktifkan tombol
Setelah dukungan kunci yang digabungkan dengan hardware perangkat berfungsi dengan benar, Anda dapat
melakukan perubahan berikut pada file fstab
perangkat agar
Android menggunakannya untuk FBE dan enkripsi metadata:
- FBE: tambahkan tanda
wrappedkey_v0
ke parameterfileencryption
. Misalnya, gunakanfileencryption=::inlinecrypt_optimized+wrappedkey_v0
. Untuk mengetahui detail selengkapnya, lihat dokumentasi FBE. - Enkripsi metadata: tambahkan tanda
wrappedkey_v0
ke parametermetadata_encryption
. Misalnya, gunakanmetadata_encryption=:wrappedkey_v0
. Untuk mengetahui detail selengkapnya, lihat dokumentasi enkripsi metadata.