Enkripsi Disk Penuh

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 flag SVC_DISABLED . Layanan yang dihentikan tidak merespons class_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).
  • 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.

  1. Deteksi sistem file yang tidak terenkripsi dengan flag forceencrypt

    /data tidak dienkripsi tetapi harus karena forceencrypt mengamanatkannya. Lepas /data .

  2. Mulai mengenkripsi /data

    vold.decrypt = "trigger_encryption" memicu init.rc , yang akan menyebabkan vold mengenkripsi /data tanpa kata sandi. (Tidak ada yang disetel karena ini seharusnya perangkat baru.)

  3. Pasang tmpfs

    vold memasang tmpfs /data (menggunakan opsi tmpfs dari ro.crypto.tmpfs_options ) dan menyetel properti vold.encrypt_progress ke 0. vold menyiapkan tmpfs /data untuk mem-boot sistem terenkripsi dan menyetel properti vold.decrypt ke: trigger_restart_min_framework

  4. 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.

  5. Saat /data dienkripsi, hapus kerangka kerja

    vold menyetel vold.decrypt ke trigger_default_encryption yang memulai layanan defaultcrypto . (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 .

  6. Pasang /data

    init lalu me-mount /data pada tmpfs RAMDisk menggunakan parameter yang diambilnya dari ro.crypto.tmpfs_options , yang disetel di init.rc .

  7. Mulai kerangka kerja

    vold menyetel vold.decrypt ke trigger_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.

  1. Periksa kata sandi

    UI memanggil vold dengan perintah cryptfs enablecrypto inplace di mana passwd adalah kata sandi layar kunci pengguna.

  2. Turunkan kerangkanya

    vold memeriksa kesalahan, mengembalikan -1 jika tidak dapat mengenkripsi, dan mencetak alasannya di log. Jika dapat mengenkripsi, ia menyetel properti vold.decrypt ke trigger_shutdown_framework . Ini menyebabkan init.rc menghentikan layanan di kelas late_start dan main .

  3. Buat catatan kaki kripto
  4. Buat file remah roti
  5. Menyalakan ulang
  6. Mendeteksi file remah roti
  7. 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.

  8. Saat mengenkripsi, pasang tmpfs

    vold memasang tmpfs /data (menggunakan opsi tmpfs dari ro.crypto.tmpfs_options ) dan menyetel properti vold.encrypt_progress ke 0. vold menyiapkan tmpfs /data untuk mem-boot sistem terenkripsi dan menyetel properti vold.decrypt ke: trigger_restart_min_framework

  9. Munculkan kerangka kerja untuk menunjukkan kemajuan

    trigger_restart_min_framework menyebabkan init.rc memulai kelas layanan main . Ketika kerangka kerja melihat bahwa vold.encrypt_progress diatur ke 0, ia menampilkan UI bilah progres, yang menanyakan properti itu setiap lima detik dan memperbarui bilah progres. Loop enkripsi memperbarui vold.encrypt_progress setiap kali mengenkripsi persen lain dari partisi.

  10. Saat /data dienkripsi, perbarui crypto footer

    Ketika /data berhasil dienkripsi, vold menghapus bendera ENCRYPTION_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 properti vold.encrypt_progress ke error_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 .

  1. Mendeteksi /data terenkripsi tanpa kata sandi

    Mendeteksi bahwa perangkat Android dienkripsi karena /data tidak dapat dipasang dan salah satu flag encryptable atau forceencrypt disetel.

    vold menyetel vold.decrypt ke trigger_default_encryption , yang memulai layanan defaultcrypto . trigger_default_encryption memeriksa jenis enkripsi untuk melihat apakah /data dienkripsi dengan atau tanpa kata sandi.

  2. Dekripsi / data

    Membuat perangkat dm-crypt di atas perangkat blok sehingga perangkat siap digunakan.

  3. Pasang /data

    vold kemudian me-mount partisi /data nyata yang didekripsi dan kemudian menyiapkan partisi baru. Itu menyetel properti vold.post_fs_data_done ke 0 dan kemudian menyetel vold.decrypt ke trigger_post_fs_data . Ini menyebabkan init.rc menjalankan perintah post-fs-data . Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetel vold.post_fs_data_done ke 1.

    Setelah vold melihat 1 di properti itu, ia menyetel properti vold.decrypt ke: trigger_restart_framework. Hal ini menyebabkan init.rc memulai kembali layanan di kelas main dan juga memulai layanan di kelas late_start untuk pertama kalinya sejak boot.

  4. 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.

  1. Mendeteksi perangkat terenkripsi dengan kata sandi

    Mendeteksi bahwa perangkat Android dienkripsi karena flag ro.crypto.state = "encrypted"

    vold menyetel vold.decrypt ke trigger_restart_min_framework karena /data dienkripsi dengan kata sandi.

  2. Pasang tmpfs

    init menyetel lima properti untuk menyimpan opsi pemasangan awal yang diberikan untuk /data dengan parameter yang diteruskan dari init.rc . vold menggunakan properti ini untuk menyiapkan pemetaan crypto:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (ASCII 8 digit angka hex diawali dengan 0x)
  3. Mulai kerangka kerja untuk meminta kata sandi

    Kerangka mulai dan melihat bahwa vold.decrypt diatur ke trigger_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 ke vold . 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 bendera CRYPTO_ENCRYPTION_IN_PROGRESS . Jika disetel, proses enkripsi terhenti, dan tidak ada data yang dapat digunakan di perangkat. Jika vold mengembalikan kesalahan, UI harus menampilkan pesan kepada pengguna untuk mem-boot ulang dan mengembalikan perangkat ke setelan pabrik, dan memberi pengguna tombol untuk menekannya.

  4. Dekripsi data dengan kata sandi

    Setelah cryptfs cryptocomplete berhasil, framework menampilkan UI yang meminta kata sandi disk. UI memeriksa kata sandi dengan mengirimkan perintah cryptfs checkpw ke vold . 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 properti ro.crypto.fs_crypto_blkdev dan mengembalikan status 0 ke UI . Jika kata sandi salah, ia mengembalikan -1 ke UI.

  5. Hentikan kerangka kerja

    UI memasang grafik boot crypto dan kemudian memanggil vold dengan perintah cryptfs restart . vold menyetel properti vold.decrypt ke trigger_reset_main , yang menyebabkan init.rc melakukan class_reset main . Ini menghentikan semua layanan di kelas utama, yang memungkinkan tmpfs /data dilepas.

  6. 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 properti vold.post_fs_data_done ke 0 dan kemudian menyetel vold.decrypt ke trigger_post_fs_data . Ini menyebabkan init.rc menjalankan perintah post-fs-data . Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetel vold.post_fs_data_done ke 1. Setelah vold melihat 1 di properti itu, ia menyetel properti vold.decrypt ke trigger_restart_framework . Hal ini menyebabkan init.rc memulai kembali layanan di kelas main dan juga memulai layanan di kelas late_start untuk pertama kalinya sejak boot.

  7. 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:

  1. Mendeteksi perangkat terenkripsi dengan kata sandi
  2. Pasang tmpfs
  3. 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:

  1. Hasilkan kunci enkripsi disk (DEK) 16 byte acak dan salt 16 byte.
  2. Terapkan scrypt ke kata sandi pengguna dan garam untuk menghasilkan kunci perantara 1 (IK1) 32-byte.
  3. 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.
  4. Masuk padded IK1 dengan HBK untuk menghasilkan IK2 256-byte.
  5. Terapkan scrypt ke IK2 dan garam (garam yang sama seperti langkah 2) untuk menghasilkan IK3 32-byte.
  6. Gunakan 16 byte pertama IK3 sebagai KEK dan 16 byte terakhir sebagai IV.
  7. 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.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

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 flag SVC_DISABLED . Layanan yang dihentikan tidak merespons class_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).
  • 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.

  1. Deteksi sistem file yang tidak terenkripsi dengan flag forceencrypt

    /data tidak dienkripsi tetapi harus karena forceencrypt mengamanatkannya. Lepas /data .

  2. Mulai mengenkripsi /data

    vold.decrypt = "trigger_encryption" memicu init.rc , yang akan menyebabkan vold mengenkripsi /data tanpa kata sandi. (Tidak ada yang disetel karena ini seharusnya perangkat baru.)

  3. Pasang tmpfs

    vold memasang tmpfs /data (menggunakan opsi tmpfs dari ro.crypto.tmpfs_options ) dan menyetel properti vold.encrypt_progress ke 0. vold menyiapkan tmpfs /data untuk mem-boot sistem terenkripsi dan menyetel properti vold.decrypt ke: trigger_restart_min_framework

  4. 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.

  5. Saat /data dienkripsi, hapus kerangka kerja

    vold menyetel vold.decrypt ke trigger_default_encryption yang memulai layanan defaultcrypto . (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 .

  6. Pasang /data

    init lalu me-mount /data pada tmpfs RAMDisk menggunakan parameter yang diambilnya dari ro.crypto.tmpfs_options , yang diatur dalam init.rc .

  7. Mulai kerangka kerja

    vold menyetel vold.decrypt ke trigger_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.

  1. Periksa kata sandi

    UI memanggil vold dengan perintah cryptfs enablecrypto inplace di mana passwd adalah kata sandi layar kunci pengguna.

  2. Turunkan kerangkanya

    vold memeriksa kesalahan, mengembalikan -1 jika tidak dapat mengenkripsi, dan mencetak alasannya di log. Jika dapat mengenkripsi, ia menyetel properti vold.decrypt ke trigger_shutdown_framework . Ini menyebabkan init.rc menghentikan layanan di kelas late_start dan main .

  3. Buat catatan kaki kripto
  4. Buat file remah roti
  5. Menyalakan ulang
  6. Mendeteksi file remah roti
  7. 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.

  8. Saat mengenkripsi, pasang tmpfs

    vold memasang tmpfs /data (menggunakan opsi tmpfs dari ro.crypto.tmpfs_options ) dan menyetel properti vold.encrypt_progress ke 0. vold menyiapkan tmpfs /data untuk mem-boot sistem terenkripsi dan menyetel properti vold.decrypt ke: trigger_restart_min_framework

  9. Munculkan kerangka kerja untuk menunjukkan kemajuan

    trigger_restart_min_framework menyebabkan init.rc memulai kelas layanan main . Ketika kerangka kerja melihat bahwa vold.encrypt_progress diatur ke 0, ia menampilkan UI bilah progres, yang menanyakan properti itu setiap lima detik dan memperbarui bilah progres. Loop enkripsi memperbarui vold.encrypt_progress setiap kali mengenkripsi persen lain dari partisi.

  10. Saat /data dienkripsi, perbarui crypto footer

    Ketika /data berhasil dienkripsi, vold menghapus bendera ENCRYPTION_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 properti vold.encrypt_progress ke error_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 .

  1. Mendeteksi /data terenkripsi tanpa kata sandi

    Mendeteksi bahwa perangkat Android dienkripsi karena /data tidak dapat dipasang dan salah satu flag encryptable atau forceencrypt disetel.

    vold menyetel vold.decrypt ke trigger_default_encryption , yang memulai layanan defaultcrypto . trigger_default_encryption memeriksa jenis enkripsi untuk melihat apakah /data dienkripsi dengan atau tanpa kata sandi.

  2. Dekripsi / data

    Membuat perangkat dm-crypt di atas perangkat blok sehingga perangkat siap digunakan.

  3. Pasang /data

    vold kemudian me-mount partisi /data nyata yang didekripsi dan kemudian menyiapkan partisi baru. Itu menyetel properti vold.post_fs_data_done ke 0 dan kemudian menyetel vold.decrypt ke trigger_post_fs_data . Ini menyebabkan init.rc menjalankan perintah post-fs-data . Mereka akan membuat direktori atau tautan yang diperlukan dan kemudian menyetel vold.post_fs_data_done ke 1.

    Setelah vold melihat 1 di properti itu, ia menyetel properti vold.decrypt ke: trigger_restart_framework. Hal ini menyebabkan init.rc memulai kembali layanan di kelas main dan juga memulai layanan di kelas late_start untuk pertama kalinya sejak boot.

  4. 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.

  1. Detect encrypted device with a password

    Detect that the Android device is encrypted because the flag ro.crypto.state = "encrypted"

    vold sets vold.decrypt to trigger_restart_min_framework because /data is encrypted with a password.

  2. Mount tmpfs

    init sets five properties to save the initial mount options given for /data with parameters passed from init.rc . vold uses these properties to set up the crypto mapping:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (ASCII 8-digit hex number preceded by 0x)
  3. Start framework to prompt for password

    The framework starts up and sees that vold.decrypt is set to trigger_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 to vold . 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 the CRYPTO_ENCRYPTION_IN_PROGRESS flag. If it's set, the encryption process was interrupted, and there is no usable data on the device. If vold 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.

  4. 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 command cryptfs checkpw to vold . 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 property ro.crypto.fs_crypto_blkdev and returns status 0 to the UI. If the password is incorrect, it returns -1 to the UI.

  5. Stop framework

    The UI puts up a crypto boot graphic and then calls vold with the command cryptfs restart . vold sets the property vold.decrypt to trigger_reset_main , which causes init.rc to do class_reset main . This stops all services in the main class, which allows the tmpfs /data to be unmounted.

  6. 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 property vold.post_fs_data_done to 0 and then sets vold.decrypt to trigger_post_fs_data . This causes init.rc to run its post-fs-data commands. They will create any necessary directories or links and then set vold.post_fs_data_done to 1. Once vold sees the 1 in that property, it sets the property vold.decrypt to trigger_restart_framework . This causes init.rc to start services in class main again and also start services in class late_start for the first time since boot.

  7. 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:

  1. Detect encrypted device with a password
  2. Mount tmpfs
  3. 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:

  1. Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
  2. Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
  3. 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.
  4. Sign padded IK1 with HBK to produce 256-byte IK2.
  5. Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
  6. Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
  7. 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 .

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

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