Enkripsi full-disk adalah proses penyandian semua data pengguna pada perangkat Android menggunakan kunci terenkripsi. Setelah perangkat dienkripsi, semua data yang dibuat pengguna secara otomatis dienkripsi sebelum memasukkannya ke disk dan semua pembacaan secara otomatis mendekripsi data sebelum mengembalikannya ke proses pemanggilan.
Enkripsi full-disk diperkenalkan ke Android pada 4.4, tetapi Android 5.0 memperkenalkan fitur-fitur baru ini:
- Dibuat enkripsi cepat, yang hanya mengenkripsi blok bekas pada partisi data untuk menghindari booting pertama memakan waktu lama. Hanya sistem file ext4 dan f2fs yang saat ini mendukung enkripsi cepat.
- Menambahkan bendera fstab
forceencrypt
untuk mengenkripsi pada boot pertama. - Menambahkan dukungan untuk pola dan enkripsi tanpa kata sandi.
- Menambahkan penyimpanan yang didukung perangkat keras dari kunci enkripsi menggunakan kemampuan penandatanganan Trusted Execution Environment (TEE) (seperti di TrustZone). Lihat Menyimpan kunci terenkripsi untuk detail lebih lanjut.
Perhatian: Perangkat yang ditingkatkan ke Android 5.0 dan kemudian dienkripsi dapat dikembalikan ke keadaan tidak terenkripsi dengan reset data pabrik. Perangkat Android 5.0 baru yang dienkripsi saat boot pertama tidak dapat dikembalikan ke keadaan tidak terenkripsi.
Cara kerja enkripsi full-disk Android
Enkripsi full-disk Android didasarkan pada dm-crypt
, yang merupakan fitur kernel yang bekerja pada lapisan perangkat blok. Karena itu, enkripsi berfungsi dengan Embedded MultiMediaCard ( eMMC) dan perangkat flash serupa yang menampilkan dirinya ke kernel sebagai perangkat blok. Enkripsi tidak dimungkinkan dengan YAFFS, yang berbicara langsung ke chip flash NAND mentah.
Algoritme enkripsinya adalah 128 Advanced Encryption Standard (AES) dengan cipher-block chaining (CBC) dan ESSIV:SHA256. Kunci master dienkripsi dengan AES 128-bit melalui panggilan ke pustaka OpenSSL. Anda harus menggunakan 128 bit atau lebih untuk kunci (dengan 256 sebagai opsional).
Catatan: OEM dapat menggunakan 128-bit atau lebih tinggi untuk mengenkripsi kunci master.
Dalam rilis Android 5.0, ada empat jenis status enkripsi:
- bawaan
- PIN
- kata sandi
- pola
Saat boot pertama, perangkat membuat kunci master 128-bit yang dibuat secara acak dan kemudian mencirikannya dengan kata sandi default dan garam yang disimpan. Kata sandi default adalah: "default_password" Namun, hash yang dihasilkan juga ditandatangani melalui TEE (seperti TrustZone), yang menggunakan tanda tangan hash untuk mengenkripsi kunci master.
Anda dapat menemukan kata sandi default yang ditentukan dalam file cryptfs.cpp Android Open Source Project.
Saat pengguna menyetel PIN/pass atau kata sandi pada perangkat, hanya kunci 128-bit yang dienkripsi ulang dan disimpan. (mis. perubahan PIN/sandi/pola pengguna TIDAK menyebabkan enkripsi ulang data pengguna.) Perhatikan bahwa perangkat yang dikelola mungkin tunduk pada pembatasan PIN, pola, atau sandi.
Enkripsi dikelola oleh init
dan vold
. init
memanggil vold
, dan vold menyetel properti untuk memicu kejadian di init. Bagian lain dari sistem juga melihat properti untuk melakukan tugas seperti melaporkan status, meminta kata sandi, atau meminta reset pabrik jika terjadi kesalahan fatal. Untuk mengaktifkan fitur enkripsi di vold
, sistem menggunakan perintah cryptfs
alat baris perintah vdc
: checkpw
, restart
, enablecrypto
, changepw
, cryptocomplete
, verifypw
, setfield
, getfield
, mountdefaultencrypted
, getpwtype
, getpw
, dan clearpw
.
Untuk mengenkripsi, mendekripsi, atau menghapus /data
, /data
tidak boleh dipasang. Namun, untuk menampilkan antarmuka pengguna (UI) apa pun, kerangka kerja harus dimulai dan kerangka kerja memerlukan /data
untuk dijalankan. Untuk mengatasi teka-teki ini, sistem file sementara dipasang di /data
. Ini memungkinkan Android untuk meminta kata sandi, menunjukkan kemajuan, atau menyarankan penghapusan data sesuai kebutuhan. Itu memberlakukan batasan bahwa untuk beralih dari sistem file sementara ke sistem file /data
yang sebenarnya, sistem harus menghentikan setiap proses dengan membuka file pada sistem file sementara dan memulai kembali proses tersebut pada sistem file /data
yang sebenarnya. Untuk melakukan ini, semua layanan harus berada dalam salah satu dari tiga grup: core
, main
, dan late_start
.
-
core
: Jangan pernah mati setelah memulai. -
main
: Matikan lalu mulai ulang setelah kata sandi disk dimasukkan. -
late_start
: Tidak dimulai sampai setelah/data
telah didekripsi dan dipasang.
Untuk memicu tindakan ini, properti vold.decrypt
disetel ke berbagai string . Untuk mematikan dan memulai ulang layanan, perintah init
adalah:
-
class_reset
: Menghentikan layanan tetapi mengizinkannya untuk dimulai ulang dengan class_start. -
class_start
: Memulai ulang layanan. -
class_stop
: Menghentikan layanan dan menambahkan flagSVC_DISABLED
. Layanan yang dihentikan tidak meresponsclass_start
.
Arus
Ada empat aliran untuk perangkat terenkripsi. Perangkat dienkripsi sekali saja dan kemudian mengikuti alur boot normal.
- Enkripsi perangkat yang sebelumnya tidak dienkripsi:
- Enkripsi perangkat baru dengan
forceencrypt
: Enkripsi wajib saat boot pertama (dimulai dari Android L). - Enkripsi perangkat yang ada: Enkripsi yang dimulai pengguna (Android K dan versi sebelumnya).
- Enkripsi perangkat baru dengan
- Boot perangkat terenkripsi:
- Memulai perangkat terenkripsi tanpa kata sandi: Mem-boot perangkat terenkripsi yang tidak memiliki kata sandi yang ditetapkan (relevan untuk perangkat yang menjalankan Android 5.0 dan yang lebih baru).
- Memulai perangkat terenkripsi dengan kata sandi: Mem-boot perangkat terenkripsi yang memiliki kata sandi yang ditetapkan.
Selain aliran ini, perangkat juga dapat gagal mengenkripsi /data
. Masing-masing aliran dijelaskan secara rinci di bawah ini.
Enkripsi perangkat baru dengan forceencrypt
Ini adalah boot pertama normal untuk perangkat Android 5.0.
- Deteksi sistem file yang tidak terenkripsi dengan flag
forceencrypt
/data
tidak dienkripsi tetapi harus karenaforceencrypt
mengamanatkannya. Lepas/data
. - Mulai mengenkripsi
/data
vold.decrypt = "trigger_encryption"
memicuinit.rc
, yang akan menyebabkanvold
mengenkripsi/data
tanpa kata sandi. (Tidak ada yang disetel karena ini seharusnya perangkat baru.) - Pasang tmpfs
vold
memasang tmpfs/data
(menggunakan opsi tmpfs dariro.crypto.tmpfs_options
) dan menyetel propertivold.encrypt_progress
ke 0.vold
menyiapkan tmpfs/data
untuk mem-boot sistem terenkripsi dan menyetel propertivold.decrypt
ke:trigger_restart_min_framework
- Munculkan kerangka kerja untuk menunjukkan kemajuan
Karena perangkat hampir tidak memiliki data untuk dienkripsi, bilah kemajuan seringkali tidak benar-benar muncul karena enkripsi terjadi begitu cepat. Lihat Mengenkripsi perangkat yang ada untuk detail selengkapnya tentang UI progres.
- Saat
/data
dienkripsi, hapus kerangka kerjavold
menyetelvold.decrypt
ketrigger_default_encryption
yang memulai layanandefaultcrypto
. (Ini memulai alur di bawah untuk memasang data pengguna terenkripsi default.)trigger_default_encryption
memeriksa jenis enkripsi untuk melihat apakah/data
dienkripsi dengan atau tanpa kata sandi. Karena perangkat Android 5.0 dienkripsi pada boot pertama, tidak boleh ada kata sandi yang ditetapkan; oleh karena itu kami mendekripsi dan memasang/data
. - Pasang
/data
init
lalu me-mount/data
pada tmpfs RAMDisk menggunakan parameter yang diambilnya dariro.crypto.tmpfs_options
, yang disetel diinit.rc
. - Mulai kerangka kerja
vold
menyetelvold.decrypt
ketrigger_restart_framework
, yang melanjutkan proses boot biasa.
Enkripsi perangkat yang ada
Inilah yang terjadi jika Anda mengenkripsi Android K yang tidak terenkripsi atau perangkat sebelumnya yang telah dimigrasikan ke L.
Proses ini dimulai oleh pengguna dan disebut sebagai "enkripsi inplace" dalam kode. Saat pengguna memilih untuk mengenkripsi perangkat, UI memastikan baterai terisi penuh dan adaptor AC terpasang sehingga ada cukup daya untuk menyelesaikan proses enkripsi.
Peringatan: Jika perangkat kehabisan daya dan mati sebelum selesai mengenkripsi, data file dibiarkan dalam keadaan terenkripsi sebagian. Perangkat harus disetel ulang pabrik dan semua data hilang.
Untuk mengaktifkan enkripsi inplace, vold
memulai loop untuk membaca setiap sektor perangkat blok nyata dan kemudian menulisnya ke perangkat blok crypto. vold
memeriksa untuk melihat apakah suatu sektor sedang digunakan sebelum membaca dan menulisnya, yang membuat enkripsi lebih cepat pada perangkat baru yang memiliki sedikit atau tanpa data.
Status perangkat : Setel ro.crypto.state = "unencrypted"
dan jalankan pemicu init
on nonencrypted
untuk melanjutkan booting.
- Periksa kata sandi
UI memanggil
vold
dengan perintahcryptfs enablecrypto inplace
di manapasswd
adalah kata sandi layar kunci pengguna. - Turunkan kerangkanya
vold
memeriksa kesalahan, mengembalikan -1 jika tidak dapat mengenkripsi, dan mencetak alasannya di log. Jika dapat mengenkripsi, ia menyetel propertivold.decrypt
ketrigger_shutdown_framework
. Ini menyebabkaninit.rc
menghentikan layanan di kelaslate_start
danmain
. - Buat catatan kaki kripto
- Buat file remah roti
- Menyalakan ulang
- Mendeteksi file remah roti
- Mulai mengenkripsi
/data
vold
kemudian menyiapkan pemetaan crypto, yang membuat perangkat blok crypto virtual yang memetakan ke perangkat blok nyata tetapi mengenkripsi setiap sektor seperti yang tertulis, dan mendekripsi setiap sektor saat dibaca.vold
kemudian membuat dan menulis metadata crypto. - Saat mengenkripsi, pasang tmpfs
vold
memasang tmpfs/data
(menggunakan opsi tmpfs dariro.crypto.tmpfs_options
) dan menyetel propertivold.encrypt_progress
ke 0.vold
menyiapkan tmpfs/data
untuk mem-boot sistem terenkripsi dan menyetel propertivold.decrypt
ke:trigger_restart_min_framework
- Munculkan kerangka kerja untuk menunjukkan kemajuan
trigger_restart_min_framework
menyebabkaninit.rc
memulai kelas layananmain
. Ketika kerangka kerja melihat bahwavold.encrypt_progress
diatur ke 0, ia menampilkan UI bilah progres, yang menanyakan properti itu setiap lima detik dan memperbarui bilah progres. Loop enkripsi memperbaruivold.encrypt_progress
setiap kali mengenkripsi persen lain dari partisi. - Saat
/data
dienkripsi, perbarui crypto footerKetika
/data
berhasil dienkripsi,vold
menghapus benderaENCRYPTION_IN_PROGRESS
di metadata.Saat perangkat berhasil dibuka kuncinya, kata sandi kemudian digunakan untuk mengenkripsi kunci master dan catatan kaki crypto diperbarui.
Jika reboot gagal karena beberapa alasan,
vold
menyetel propertivold.encrypt_progress
keerror_reboot_failed
dan UI akan menampilkan pesan yang meminta pengguna menekan tombol untuk melakukan boot ulang. Hal ini diperkirakan tidak akan pernah terjadi.
Memulai perangkat terenkripsi dengan enkripsi default
Inilah yang terjadi ketika Anda mem-boot perangkat terenkripsi tanpa kata sandi. Karena perangkat Android 5.0 dienkripsi pada boot pertama, tidak boleh ada kata sandi yang ditetapkan dan oleh karena itu ini adalah status enkripsi default .
- Mendeteksi
/data
terenkripsi tanpa kata sandiMendeteksi bahwa perangkat Android dienkripsi karena
/data
tidak dapat dipasang dan salah satu flagencryptable
atauforceencrypt
disetel.vold
menyetelvold.decrypt
ketrigger_default_encryption
, yang memulai layanandefaultcrypto
.trigger_default_encryption
memeriksa jenis enkripsi untuk melihat apakah/data
dienkripsi dengan atau tanpa kata sandi. - Dekripsi / data
Membuat perangkat
dm-crypt
di atas perangkat blok sehingga perangkat siap digunakan. - Pasang /data
vold
kemudian me-mount partisi/data
nyata yang didekripsi dan kemudian menyiapkan partisi baru. Itu menyetel propertivold.post_fs_data_done
ke 0 dan kemudian menyetelvold.decrypt
ketrigger_post_fs_data
. Ini menyebabkaninit.rc
menjalankan perintahpost-fs-data
. Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetelvold.post_fs_data_done
ke 1.Setelah
vold
melihat 1 di properti itu, ia menyetel propertivold.decrypt
ke:trigger_restart_framework.
Hal ini menyebabkaninit.rc
memulai kembali layanan di kelasmain
dan juga memulai layanan di kelaslate_start
untuk pertama kalinya sejak boot. - Mulai kerangka kerja
Sekarang kerangka mem-boot semua layanannya menggunakan
/data
yang didekripsi, dan sistem siap digunakan.
Memulai perangkat terenkripsi tanpa enkripsi default
Inilah yang terjadi ketika Anda mem-boot perangkat terenkripsi yang memiliki kata sandi yang ditetapkan. Kata sandi perangkat dapat berupa pin, pola, atau kata sandi.
- Mendeteksi perangkat terenkripsi dengan kata sandi
Mendeteksi bahwa perangkat Android dienkripsi karena flag
ro.crypto.state = "encrypted"
vold
menyetelvold.decrypt
ketrigger_restart_min_framework
karena/data
dienkripsi dengan kata sandi. - Pasang tmpfs
init
menyetel lima properti untuk menyimpan opsi pemasangan awal yang diberikan untuk/data
dengan parameter yang diteruskan dariinit.rc
.vold
menggunakan properti ini untuk menyiapkan pemetaan crypto:-
ro.crypto.fs_type
-
ro.crypto.fs_real_blkdev
-
ro.crypto.fs_mnt_point
-
ro.crypto.fs_options
-
ro.crypto.fs_flags
(ASCII 8 digit angka hex diawali dengan 0x)
-
- Mulai kerangka kerja untuk meminta kata sandi
Kerangka mulai dan melihat bahwa
vold.decrypt
diatur ketrigger_restart_min_framework
. Ini memberi tahu kerangka kerja bahwa ia mem-boot pada disk tmpfs/data
dan perlu mendapatkan kata sandi pengguna.Namun, pertama-tama, perlu memastikan bahwa disk telah dienkripsi dengan benar. Ini mengirimkan perintah
cryptfs cryptocomplete
kevold
.vold
mengembalikan 0 jika enkripsi berhasil diselesaikan, -1 pada kesalahan internal, atau -2 jika enkripsi tidak berhasil diselesaikan.vold
menentukan ini dengan melihat metadata crypto untuk benderaCRYPTO_ENCRYPTION_IN_PROGRESS
. Jika disetel, proses enkripsi terhenti, dan tidak ada data yang dapat digunakan di perangkat. Jikavold
mengembalikan kesalahan, UI harus menampilkan pesan kepada pengguna untuk mem-boot ulang dan mengembalikan perangkat ke setelan pabrik, dan memberi pengguna tombol untuk menekannya. - Dekripsi data dengan kata sandi
Setelah
cryptfs cryptocomplete
berhasil, framework menampilkan UI yang meminta kata sandi disk. UI memeriksa kata sandi dengan mengirimkan perintahcryptfs checkpw
kevold
. Jika kata sandi benar (yang ditentukan dengan berhasil memasang/data
yang didekripsi di lokasi sementara, lalu melepasnya),vold
menyimpan nama perangkat blok yang didekripsi di propertiro.crypto.fs_crypto_blkdev
dan mengembalikan status 0 ke UI . Jika kata sandi salah, ia mengembalikan -1 ke UI. - Hentikan kerangka kerja
UI memasang grafik boot crypto dan kemudian memanggil
vold
dengan perintahcryptfs restart
.vold
menyetel propertivold.decrypt
ketrigger_reset_main
, yang menyebabkaninit.rc
melakukanclass_reset main
. Ini menghentikan semua layanan di kelas utama, yang memungkinkan tmpfs/data
dilepas. - Pasang
/data
vold
kemudian me-mount partisi/data
nyata yang didekripsi dan menyiapkan partisi baru (yang mungkin tidak pernah disiapkan jika dienkripsi dengan opsi penghapusan, yang tidak didukung pada rilis pertama). Itu menyetel propertivold.post_fs_data_done
ke 0 dan kemudian menyetelvold.decrypt
ketrigger_post_fs_data
. Ini menyebabkaninit.rc
menjalankan perintahpost-fs-data
. Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetelvold.post_fs_data_done
ke 1. Setelahvold
melihat 1 di properti itu, ia menyetel propertivold.decrypt
ketrigger_restart_framework
. Hal ini menyebabkaninit.rc
memulai kembali layanan di kelasmain
dan juga memulai layanan di kelaslate_start
untuk pertama kalinya sejak boot. - Mulai kerangka kerja penuh
Sekarang kerangka mem-boot semua layanannya menggunakan sistem file
/data
yang didekripsi, dan sistem siap digunakan.
Kegagalan
Perangkat yang gagal mendekripsi mungkin salah karena beberapa alasan. Perangkat memulai dengan serangkaian langkah normal untuk mem-boot:
- Mendeteksi perangkat terenkripsi dengan kata sandi
- Pasang tmpfs
- Mulai kerangka kerja untuk meminta kata sandi
Namun setelah kerangka terbuka, perangkat dapat mengalami beberapa kesalahan:
- Kata sandi cocok tetapi tidak dapat mendekripsi data
- Pengguna memasukkan kata sandi yang salah sebanyak 30 kali
Jika kesalahan ini tidak teratasi, minta pengguna untuk menghapus pabrik :
Jika vold
mendeteksi kesalahan selama proses enkripsi, dan jika belum ada data yang dihancurkan dan kerangka kerja aktif, vold
mengatur properti vold.encrypt_progress
menjadi error_not_encrypted
. UI meminta pengguna untuk mem-boot ulang dan memberi tahu mereka bahwa proses enkripsi tidak pernah dimulai. Jika kesalahan terjadi setelah kerangka kerja diruntuhkan, tetapi sebelum bilah progres UI aktif, vold
akan mem-boot ulang sistem. Jika reboot gagal, vold.encrypt_progress
disetel ke error_shutting_down
dan mengembalikan -1; tapi tidak akan ada apa-apa untuk menangkap kesalahan. Ini tidak diharapkan terjadi.
Jika vold
mendeteksi kesalahan selama proses enkripsi, vold.encrypt_progress
disetel ke error_partially_encrypted
dan mengembalikan -1. UI kemudian akan menampilkan pesan yang menyatakan bahwa enkripsi gagal dan menyediakan tombol bagi pengguna untuk menyetel ulang perangkat ke setelan pabrik.
Menyimpan kunci terenkripsi
Kunci terenkripsi disimpan dalam metadata crypto. Dukungan perangkat keras diimplementasikan dengan menggunakan kemampuan penandatanganan Trusted Execution Environment (TEE). Sebelumnya, kami mengenkripsi kunci master dengan kunci yang dibuat dengan menerapkan scrypt ke kata sandi pengguna dan garam yang disimpan. Untuk membuat kunci tahan terhadap serangan off-box, kami memperluas algoritme ini dengan menandatangani kunci yang dihasilkan dengan kunci TEE yang disimpan. Tanda tangan yang dihasilkan kemudian diubah menjadi kunci panjang yang sesuai dengan satu lagi aplikasi scrypt. Kunci ini kemudian digunakan untuk mengenkripsi dan mendekripsi kunci master. Untuk menyimpan kunci ini:
- Hasilkan kunci enkripsi disk (DEK) 16 byte acak dan salt 16 byte.
- Terapkan scrypt ke kata sandi pengguna dan garam untuk menghasilkan kunci perantara 1 (IK1) 32-byte.
- Pad IK1 dengan nol byte dengan ukuran kunci pribadi terikat perangkat keras (HBK). Secara khusus, kami pad sebagai: 00 || IK1 || 00..00; satu nol byte, 32 IK1 byte, 223 nol byte.
- Masuk padded IK1 dengan HBK untuk menghasilkan IK2 256-byte.
- Terapkan scrypt ke IK2 dan garam (garam yang sama seperti langkah 2) untuk menghasilkan IK3 32-byte.
- Gunakan 16 byte pertama IK3 sebagai KEK dan 16 byte terakhir sebagai IV.
- Enkripsi DEK dengan AES_CBC, dengan kunci KEK, dan vektor inisialisasi IV.
Mengubah kata sandi
Saat pengguna memilih untuk mengubah atau menghapus kata sandinya di pengaturan, UI mengirimkan perintah cryptfs changepw
ke vold
, dan vold
mengenkripsi ulang kunci master disk dengan kata sandi baru.
Properti enkripsi
vold
dan init
berkomunikasi satu sama lain dengan menyetel properti. Berikut adalah daftar properti yang tersedia untuk enkripsi.
Sifat Vold
Properti | Keterangan |
---|---|
vold.decrypt trigger_encryption | Enkripsi drive tanpa kata sandi. |
vold.decrypt trigger_default_encryption | Periksa drive untuk melihat apakah itu dienkripsi tanpa kata sandi. Jika ya, dekripsi dan pasang, jika tidak atur vold.decrypt ke trigger_restart_min_framework. |
vold.decrypt trigger_reset_main | Diatur oleh vold untuk mematikan UI yang meminta kata sandi disk. |
vold.decrypt trigger_post_fs_data | Diatur oleh vold ke prep /data dengan direktori yang diperlukan, et al. |
vold.decrypt trigger_restart_framework | Ditetapkan oleh vold untuk memulai kerangka nyata dan semua layanan. |
vold.decrypt trigger_shutdown_framework | Diatur oleh vold untuk mematikan kerangka kerja penuh untuk memulai enkripsi. |
vold.decrypt trigger_restart_min_framework | Diatur oleh vold untuk memulai bilah progres UI untuk enkripsi atau meminta kata sandi, tergantung pada nilai ro.crypto.state . |
vold.encrypt_progress | Saat kerangka kerja dijalankan, jika properti ini disetel, masuk ke mode UI bilah kemajuan. |
vold.encrypt_progress 0 to 100 | UI bilah kemajuan harus menampilkan nilai persentase yang ditetapkan. |
vold.encrypt_progress error_partially_encrypted | UI progress bar akan menampilkan pesan bahwa enkripsi gagal, dan memberi pengguna opsi untuk mengatur ulang perangkat ke setelan pabrik. |
vold.encrypt_progress error_reboot_failed | UI progress bar harus menampilkan pesan yang mengatakan enkripsi selesai, dan memberi pengguna tombol untuk mem-boot ulang perangkat. Kesalahan ini tidak diharapkan terjadi. |
vold.encrypt_progress error_not_encrypted | UI bilah kemajuan harus menampilkan pesan yang mengatakan bahwa terjadi kesalahan, tidak ada data yang dienkripsi atau hilang, dan memberi pengguna tombol untuk mem-boot ulang sistem. |
vold.encrypt_progress error_shutting_down | UI bilah kemajuan tidak berjalan, jadi tidak jelas siapa yang akan merespons kesalahan ini. Dan itu seharusnya tidak pernah terjadi. |
vold.post_fs_data_done 0 | Diatur oleh vold tepat sebelum menyetel vold.decrypt ke trigger_post_fs_data . |
vold.post_fs_data_done 1 | Diatur oleh init.rc atau init.rc setelah menyelesaikan tugas post-fs-data . |
properti init
Properti | Keterangan |
---|---|
ro.crypto.fs_crypto_blkdev | Diatur oleh perintah vold checkpw untuk digunakan nanti oleh perintah vold restart . |
ro.crypto.state unencrypted | Ditetapkan oleh init untuk mengatakan bahwa sistem ini berjalan dengan /data ro.crypto.state encrypted . Ditetapkan oleh init untuk mengatakan sistem ini berjalan dengan /data terenkripsi. |
| Kelima properti ini diatur oleh init ketika mencoba untuk me-mount /data dengan parameter yang diteruskan dari init.rc . vold menggunakan ini untuk mengatur pemetaan crypto. |
ro.crypto.tmpfs_options | Diatur oleh init.rc dengan opsi yang harus digunakan init saat memasang sistem file tmpfs /data . |
Init tindakan
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption,
Enkripsi full-disk adalah proses penyandian semua data pengguna pada perangkat Android menggunakan kunci terenkripsi. Setelah perangkat dienkripsi, semua data yang dibuat pengguna secara otomatis dienkripsi sebelum memasukkannya ke disk dan semua pembacaan secara otomatis mendekripsi data sebelum mengembalikannya ke proses pemanggilan.
Enkripsi full-disk diperkenalkan ke Android pada 4.4, tetapi Android 5.0 memperkenalkan fitur-fitur baru ini:
- Dibuat enkripsi cepat, yang hanya mengenkripsi blok bekas pada partisi data untuk menghindari booting pertama memakan waktu lama. Hanya sistem file ext4 dan f2fs yang saat ini mendukung enkripsi cepat.
- Menambahkan bendera fstab
forceencrypt
untuk mengenkripsi pada boot pertama. - Menambahkan dukungan untuk pola dan enkripsi tanpa kata sandi.
- Menambahkan penyimpanan yang didukung perangkat keras dari kunci enkripsi menggunakan kemampuan penandatanganan Trusted Execution Environment (TEE) (seperti di TrustZone). Lihat Menyimpan kunci terenkripsi untuk detail lebih lanjut.
Perhatian: Perangkat yang ditingkatkan ke Android 5.0 dan kemudian dienkripsi dapat dikembalikan ke keadaan tidak terenkripsi dengan reset data pabrik. Perangkat Android 5.0 baru yang dienkripsi saat boot pertama tidak dapat dikembalikan ke keadaan tidak terenkripsi.
Cara kerja enkripsi full-disk Android
Enkripsi full-disk Android didasarkan pada dm-crypt
, yang merupakan fitur kernel yang bekerja pada lapisan perangkat blok. Karena itu, enkripsi berfungsi dengan Embedded MultiMediaCard ( eMMC) dan perangkat flash serupa yang menampilkan dirinya ke kernel sebagai perangkat blok. Enkripsi tidak dimungkinkan dengan YAFFS, yang berbicara langsung ke chip flash NAND mentah.
Algoritme enkripsinya adalah 128 Advanced Encryption Standard (AES) dengan cipher-block chaining (CBC) dan ESSIV:SHA256. Kunci master dienkripsi dengan AES 128-bit melalui panggilan ke pustaka OpenSSL. Anda harus menggunakan 128 bit atau lebih untuk kunci (dengan 256 sebagai opsional).
Catatan: OEM dapat menggunakan 128-bit atau lebih tinggi untuk mengenkripsi kunci master.
Dalam rilis Android 5.0, ada empat jenis status enkripsi:
- bawaan
- PIN
- kata sandi
- pola
Saat boot pertama, perangkat membuat kunci master 128-bit yang dibuat secara acak dan kemudian mencirikannya dengan kata sandi default dan garam yang disimpan. Kata sandi default adalah: "default_password" Namun, hash yang dihasilkan juga ditandatangani melalui TEE (seperti TrustZone), yang menggunakan tanda tangan hash untuk mengenkripsi kunci master.
Anda dapat menemukan kata sandi default yang ditentukan dalam file cryptfs.cpp Android Open Source Project.
Saat pengguna menyetel PIN/pass atau kata sandi pada perangkat, hanya kunci 128-bit yang dienkripsi ulang dan disimpan. (mis. perubahan PIN/sandi/pola pengguna TIDAK menyebabkan enkripsi ulang data pengguna.) Perhatikan bahwa perangkat yang dikelola mungkin tunduk pada pembatasan PIN, pola, atau sandi.
Enkripsi dikelola oleh init
dan vold
. init
memanggil vold
, dan vold menyetel properti untuk memicu kejadian di init. Bagian lain dari sistem juga melihat properti untuk melakukan tugas seperti melaporkan status, meminta kata sandi, atau meminta reset pabrik jika terjadi kesalahan fatal. Untuk mengaktifkan fitur enkripsi di vold
, sistem menggunakan perintah cryptfs
alat baris perintah vdc
: checkpw
, restart
, enablecrypto
, changepw
, cryptocomplete
, verifypw
, setfield
, getfield
, mountdefaultencrypted
, getpwtype
, getpw
, dan clearpw
.
Untuk mengenkripsi, mendekripsi, atau menghapus /data
, /data
tidak boleh dipasang. Namun, untuk menampilkan antarmuka pengguna (UI) apa pun, kerangka kerja harus dimulai dan kerangka kerja memerlukan /data
untuk dijalankan. Untuk mengatasi teka-teki ini, sistem file sementara dipasang di /data
. Ini memungkinkan Android untuk meminta kata sandi, menunjukkan kemajuan, atau menyarankan penghapusan data sesuai kebutuhan. Itu memberlakukan batasan bahwa untuk beralih dari sistem file sementara ke sistem file /data
yang sebenarnya, sistem harus menghentikan setiap proses dengan membuka file pada sistem file sementara dan memulai kembali proses tersebut pada sistem file /data
yang sebenarnya. Untuk melakukan ini, semua layanan harus berada dalam salah satu dari tiga grup: core
, main
, dan late_start
.
-
core
: Jangan pernah mati setelah memulai. -
main
: Matikan lalu mulai ulang setelah kata sandi disk dimasukkan. -
late_start
: Tidak dimulai sampai setelah/data
telah didekripsi dan dipasang.
Untuk memicu tindakan ini, properti vold.decrypt
disetel ke berbagai string . Untuk mematikan dan memulai ulang layanan, perintah init
adalah:
-
class_reset
: Menghentikan layanan tetapi mengizinkannya untuk dimulai ulang dengan class_start. -
class_start
: Memulai ulang layanan. -
class_stop
: Menghentikan layanan dan menambahkan flagSVC_DISABLED
. Layanan yang dihentikan tidak meresponsclass_start
.
Arus
Ada empat aliran untuk perangkat terenkripsi. Perangkat dienkripsi sekali saja dan kemudian mengikuti alur boot normal.
- Enkripsi perangkat yang sebelumnya tidak dienkripsi:
- Enkripsi perangkat baru dengan
forceencrypt
: Enkripsi wajib saat boot pertama (dimulai dari Android L). - Enkripsi perangkat yang ada: Enkripsi yang dimulai pengguna (Android K dan versi sebelumnya).
- Enkripsi perangkat baru dengan
- Boot perangkat terenkripsi:
- Memulai perangkat terenkripsi tanpa kata sandi: Mem-boot perangkat terenkripsi yang tidak memiliki kata sandi yang ditetapkan (relevan untuk perangkat yang menjalankan Android 5.0 dan yang lebih baru).
- Memulai perangkat terenkripsi dengan kata sandi: Mem-boot perangkat terenkripsi yang memiliki kata sandi yang ditetapkan.
Selain aliran ini, perangkat juga dapat gagal mengenkripsi /data
. Masing-masing aliran dijelaskan secara rinci di bawah ini.
Enkripsi perangkat baru dengan forceencrypt
Ini adalah boot pertama normal untuk perangkat Android 5.0.
- Deteksi sistem file yang tidak terenkripsi dengan flag
forceencrypt
/data
tidak dienkripsi tetapi harus karenaforceencrypt
mengamanatkannya. Lepas/data
. - Mulai mengenkripsi
/data
vold.decrypt = "trigger_encryption"
memicuinit.rc
, yang akan menyebabkanvold
mengenkripsi/data
tanpa kata sandi. (Tidak ada yang disetel karena ini seharusnya perangkat baru.) - Pasang tmpfs
vold
memasang tmpfs/data
(menggunakan opsi tmpfs dariro.crypto.tmpfs_options
) dan menyetel propertivold.encrypt_progress
ke 0.vold
menyiapkan tmpfs/data
untuk mem-boot sistem terenkripsi dan menyetel propertivold.decrypt
ke:trigger_restart_min_framework
- Munculkan kerangka kerja untuk menunjukkan kemajuan
Karena perangkat hampir tidak memiliki data untuk dienkripsi, bilah kemajuan seringkali tidak benar-benar muncul karena enkripsi terjadi begitu cepat. Lihat Mengenkripsi perangkat yang ada untuk detail selengkapnya tentang UI progres.
- Saat
/data
dienkripsi, hapus kerangka kerjavold
menyetelvold.decrypt
ketrigger_default_encryption
yang memulai layanandefaultcrypto
. (Ini memulai alur di bawah untuk memasang data pengguna terenkripsi default.)trigger_default_encryption
memeriksa jenis enkripsi untuk melihat apakah/data
dienkripsi dengan atau tanpa kata sandi. Karena perangkat Android 5.0 dienkripsi pada boot pertama, tidak boleh ada kata sandi yang ditetapkan; oleh karena itu kami mendekripsi dan memasang/data
. - Pasang
/data
init
lalu me-mount/data
pada tmpfs RAMDisk menggunakan parameter yang diambilnya dariro.crypto.tmpfs_options
, yang diatur dalaminit.rc
. - Mulai kerangka kerja
vold
menyetelvold.decrypt
ketrigger_restart_framework
, yang melanjutkan proses boot biasa.
Enkripsi perangkat yang ada
Inilah yang terjadi jika Anda mengenkripsi Android K yang tidak terenkripsi atau perangkat sebelumnya yang telah dimigrasikan ke L.
Proses ini dimulai oleh pengguna dan disebut sebagai "enkripsi inplace" dalam kode. Saat pengguna memilih untuk mengenkripsi perangkat, UI memastikan baterai terisi penuh dan adaptor AC terpasang sehingga ada cukup daya untuk menyelesaikan proses enkripsi.
Peringatan: Jika perangkat kehabisan daya dan mati sebelum selesai mengenkripsi, data file dibiarkan dalam keadaan terenkripsi sebagian. Perangkat harus disetel ulang pabrik dan semua data hilang.
Untuk mengaktifkan enkripsi inplace, vold
memulai loop untuk membaca setiap sektor perangkat blok nyata dan kemudian menulisnya ke perangkat blok crypto. vold
memeriksa untuk melihat apakah suatu sektor sedang digunakan sebelum membaca dan menulisnya, yang membuat enkripsi lebih cepat pada perangkat baru yang memiliki sedikit atau tanpa data.
Status perangkat : Setel ro.crypto.state = "unencrypted"
dan jalankan pemicu init
on nonencrypted
untuk melanjutkan booting.
- Periksa kata sandi
UI memanggil
vold
dengan perintahcryptfs enablecrypto inplace
di manapasswd
adalah kata sandi layar kunci pengguna. - Turunkan kerangkanya
vold
memeriksa kesalahan, mengembalikan -1 jika tidak dapat mengenkripsi, dan mencetak alasannya di log. Jika dapat mengenkripsi, ia menyetel propertivold.decrypt
ketrigger_shutdown_framework
. Ini menyebabkaninit.rc
menghentikan layanan di kelaslate_start
danmain
. - Buat catatan kaki kripto
- Buat file remah roti
- Menyalakan ulang
- Mendeteksi file remah roti
- Mulai mengenkripsi
/data
vold
kemudian menyiapkan pemetaan crypto, yang membuat perangkat blok crypto virtual yang memetakan ke perangkat blok nyata tetapi mengenkripsi setiap sektor seperti yang tertulis, dan mendekripsi setiap sektor saat dibaca.vold
kemudian membuat dan menulis metadata crypto. - Saat mengenkripsi, pasang tmpfs
vold
memasang tmpfs/data
(menggunakan opsi tmpfs dariro.crypto.tmpfs_options
) dan menyetel propertivold.encrypt_progress
ke 0.vold
menyiapkan tmpfs/data
untuk mem-boot sistem terenkripsi dan menyetel propertivold.decrypt
ke:trigger_restart_min_framework
- Munculkan kerangka kerja untuk menunjukkan kemajuan
trigger_restart_min_framework
menyebabkaninit.rc
memulai kelas layananmain
. Ketika kerangka kerja melihat bahwavold.encrypt_progress
diatur ke 0, ia menampilkan UI bilah progres, yang menanyakan properti itu setiap lima detik dan memperbarui bilah progres. Loop enkripsi memperbaruivold.encrypt_progress
setiap kali mengenkripsi persen lain dari partisi. - Saat
/data
dienkripsi, perbarui crypto footerKetika
/data
berhasil dienkripsi,vold
menghapus benderaENCRYPTION_IN_PROGRESS
di metadata.Saat perangkat berhasil dibuka kuncinya, kata sandi kemudian digunakan untuk mengenkripsi kunci master dan catatan kaki crypto diperbarui.
Jika reboot gagal karena beberapa alasan,
vold
menyetel propertivold.encrypt_progress
keerror_reboot_failed
dan UI akan menampilkan pesan yang meminta pengguna menekan tombol untuk melakukan boot ulang. Hal ini diperkirakan tidak akan pernah terjadi.
Memulai perangkat terenkripsi dengan enkripsi default
Inilah yang terjadi ketika Anda mem-boot perangkat terenkripsi tanpa kata sandi. Karena perangkat Android 5.0 dienkripsi pada boot pertama, tidak boleh ada kata sandi yang ditetapkan dan oleh karena itu ini adalah status enkripsi default .
- Mendeteksi
/data
terenkripsi tanpa kata sandiMendeteksi bahwa perangkat Android dienkripsi karena
/data
tidak dapat dipasang dan salah satu flagencryptable
atauforceencrypt
disetel.vold
menyetelvold.decrypt
ketrigger_default_encryption
, yang memulai layanandefaultcrypto
.trigger_default_encryption
memeriksa jenis enkripsi untuk melihat apakah/data
dienkripsi dengan atau tanpa kata sandi. - Dekripsi / data
Membuat perangkat
dm-crypt
di atas perangkat blok sehingga perangkat siap digunakan. - Pasang /data
vold
kemudian me-mount partisi/data
nyata yang didekripsi dan kemudian menyiapkan partisi baru. Itu menyetel propertivold.post_fs_data_done
ke 0 dan kemudian menyetelvold.decrypt
ketrigger_post_fs_data
. Ini menyebabkaninit.rc
menjalankan perintahpost-fs-data
. Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetelvold.post_fs_data_done
ke 1.Setelah
vold
melihat 1 di properti itu, ia menyetel propertivold.decrypt
ke:trigger_restart_framework.
Hal ini menyebabkaninit.rc
memulai kembali layanan di kelasmain
dan juga memulai layanan di kelaslate_start
untuk pertama kalinya sejak boot. - Mulai kerangka kerja
Sekarang kerangka mem-boot semua layanannya menggunakan
/data
yang didekripsi, dan sistem siap digunakan.
Starting an encrypted device without default encryption
This is what happens when you boot up an encrypted device that has a set password. The device's password can be a pin, pattern, or password.
- Detect encrypted device with a password
Detect that the Android device is encrypted because the flag
ro.crypto.state = "encrypted"
vold
setsvold.decrypt
totrigger_restart_min_framework
because/data
is encrypted with a password. - Mount tmpfs
init
sets five properties to save the initial mount options given for/data
with parameters passed frominit.rc
.vold
uses these properties to set up the crypto mapping:-
ro.crypto.fs_type
-
ro.crypto.fs_real_blkdev
-
ro.crypto.fs_mnt_point
-
ro.crypto.fs_options
-
ro.crypto.fs_flags
(ASCII 8-digit hex number preceded by 0x)
-
- Start framework to prompt for password
The framework starts up and sees that
vold.decrypt
is set totrigger_restart_min_framework
. This tells the framework that it is booting on a tmpfs/data
disk and it needs to get the user password.First, however, it needs to make sure that the disk was properly encrypted. It sends the command
cryptfs cryptocomplete
tovold
.vold
returns 0 if encryption was completed successfully, -1 on internal error, or -2 if encryption was not completed successfully.vold
determines this by looking in the crypto metadata for theCRYPTO_ENCRYPTION_IN_PROGRESS
flag. If it's set, the encryption process was interrupted, and there is no usable data on the device. Ifvold
returns an error, the UI should display a message to the user to reboot and factory reset the device, and give the user a button to press to do so. - Decrypt data with password
Once
cryptfs cryptocomplete
is successful, the framework displays a UI asking for the disk password. The UI checks the password by sending the commandcryptfs checkpw
tovold
. If the password is correct (which is determined by successfully mounting the decrypted/data
at a temporary location, then unmounting it),vold
saves the name of the decrypted block device in the propertyro.crypto.fs_crypto_blkdev
and returns status 0 to the UI. If the password is incorrect, it returns -1 to the UI. - Stop framework
The UI puts up a crypto boot graphic and then calls
vold
with the commandcryptfs restart
.vold
sets the propertyvold.decrypt
totrigger_reset_main
, which causesinit.rc
to doclass_reset main
. This stops all services in the main class, which allows the tmpfs/data
to be unmounted. - Mount
/data
vold
then mounts the decrypted real/data
partition and prepares the new partition (which may never have been prepared if it was encrypted with the wipe option, which is not supported on first release). It sets the propertyvold.post_fs_data_done
to 0 and then setsvold.decrypt
totrigger_post_fs_data
. This causesinit.rc
to run itspost-fs-data
commands. They will create any necessary directories or links and then setvold.post_fs_data_done
to 1. Oncevold
sees the 1 in that property, it sets the propertyvold.decrypt
totrigger_restart_framework
. This causesinit.rc
to start services in classmain
again and also start services in classlate_start
for the first time since boot. - Start full framework
Now the framework boots all its services using the decrypted
/data
filesystem, and the system is ready for use.
Failure
A device that fails to decrypt might be awry for a few reasons. The device starts with the normal series of steps to boot:
- Detect encrypted device with a password
- Mount tmpfs
- Start framework to prompt for password
But after the framework opens, the device can encounter some errors:
- Password matches but cannot decrypt data
- User enters wrong password 30 times
If these errors are not resolved, prompt user to factory wipe :
If vold
detects an error during the encryption process, and if no data has been destroyed yet and the framework is up, vold
sets the property vold.encrypt_progress
to error_not_encrypted
. The UI prompts the user to reboot and alerts them the encryption process never started. If the error occurs after the framework has been torn down, but before the progress bar UI is up, vold
will reboot the system. If the reboot fails, it sets vold.encrypt_progress
to error_shutting_down
and returns -1; but there will not be anything to catch the error. This is not expected to happen.
If vold
detects an error during the encryption process, it sets vold.encrypt_progress
to error_partially_encrypted
and returns -1. The UI should then display a message saying the encryption failed and provide a button for the user to factory reset the device.
Storing the encrypted key
The encrypted key is stored in the crypto metadata. Hardware backing is implemented by using Trusted Execution Environment's (TEE) signing capability. Previously, we encrypted the master key with a key generated by applying scrypt to the user's password and the stored salt. In order to make the key resilient against off-box attacks, we extend this algorithm by signing the resultant key with a stored TEE key. The resultant signature is then turned into an appropriate length key by one more application of scrypt. This key is then used to encrypt and decrypt the master key. To store this key:
- Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
- Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
- Pad IK1 with zero bytes to the size of the hardware-bound private key (HBK). Specifically, we pad as: 00 || IK1 || 00..00; one zero byte, 32 IK1 bytes, 223 zero bytes.
- Sign padded IK1 with HBK to produce 256-byte IK2.
- Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
- Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
- Encrypt DEK with AES_CBC, with key KEK, and initialization vector IV.
Changing the password
When a user elects to change or remove their password in settings, the UI sends the command cryptfs changepw
to vold
, and vold
re-encrypts the disk master key with the new password.
Encryption properties
vold
and init
communicate with each other by setting properties. Here is a list of available properties for encryption.
Vold properties
Property | Keterangan |
---|---|
vold.decrypt trigger_encryption | Encrypt the drive with no password. |
vold.decrypt trigger_default_encryption | Check the drive to see if it is encrypted with no password. If it is, decrypt and mount it, else set vold.decrypt to trigger_restart_min_framework. |
vold.decrypt trigger_reset_main | Set by vold to shutdown the UI asking for the disk password. |
vold.decrypt trigger_post_fs_data | Set by vold to prep /data with necessary directories, et al. |
vold.decrypt trigger_restart_framework | Set by vold to start the real framework and all services. |
vold.decrypt trigger_shutdown_framework | Set by vold to shutdown the full framework to start encryption. |
vold.decrypt trigger_restart_min_framework | Set by vold to start the progress bar UI for encryption or prompt for password, depending on the value of ro.crypto.state . |
vold.encrypt_progress | When the framework starts up, if this property is set, enter the progress bar UI mode. |
vold.encrypt_progress 0 to 100 | The progress bar UI should display the percentage value set. |
vold.encrypt_progress error_partially_encrypted | The progress bar UI should display a message that the encryption failed, and give the user an option to factory reset the device. |
vold.encrypt_progress error_reboot_failed | The progress bar UI should display a message saying encryption completed, and give the user a button to reboot the device. This error is not expected to happen. |
vold.encrypt_progress error_not_encrypted | The progress bar UI should display a message saying an error occurred, no data was encrypted or lost, and give the user a button to reboot the system. |
vold.encrypt_progress error_shutting_down | The progress bar UI is not running, so it is unclear who will respond to this error. And it should never happen anyway. |
vold.post_fs_data_done 0 | Set by vold just before setting vold.decrypt to trigger_post_fs_data . |
vold.post_fs_data_done 1 | Set by init.rc or init.rc just after finishing the task post-fs-data . |
init properties
Property | Keterangan |
---|---|
ro.crypto.fs_crypto_blkdev | Set by the vold command checkpw for later use by the vold command restart . |
ro.crypto.state unencrypted | Set by init to say this system is running with an unencrypted /data ro.crypto.state encrypted . Set by init to say this system is running with an encrypted /data . |
| These five properties are set by init when it tries to mount /data with parameters passed in from init.rc . vold uses these to setup the crypto mapping. |
ro.crypto.tmpfs_options | Set by init.rc with the options init should use when mounting the tmpfs /data filesystem. |
Init actions
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption