Menerapkan dm-verity

Android 4.4 dan yang lebih tinggi mendukung Booting Terverifikasi melalui fitur kernel device-mapper-verity (dm-verity) opsional, yang memberikan pemeriksaan integritas transparan pada perangkat blok. dm-verity membantu mencegah rootkit persisten yang dapat mempertahankan hak istimewa root dan membahayakan perangkat. Ini membantu pengguna Android memastikan bahwa saat {i>booting<i} perangkat, perangkat itu berada di tempat yang sama seperti saat terakhir kali digunakan.

Aplikasi yang Berpotensi Membahayakan (PHA) dengan hak istimewa root dapat disembunyikan dari program deteksi dan menyamarkan diri mereka sendiri. Perangkat lunak {i>rooting<i} dapat melakukan ini karena sering kali lebih istimewa daripada detektor, yang memungkinkan perangkat lunak untuk "berbohong" ke program deteksi.

Fitur dm-verity memungkinkan Anda melihat perangkat blok, penyimpanan yang mendasarinya, lapisan sistem file, dan menentukan apakah sesuai dengan kriteria konfigurasi Anda. Hal ini dilakukan dengan menggunakan pohon {i>hash<i} kriptografi. Untuk setiap blok (biasanya 4k), ada hash SHA256.

Karena nilai {i>hash<i} disimpan di hierarki halaman, hanya {i>hash <i}tingkat atas "akar" {i>hash <i}harus dipercaya untuk memverifikasi bagian pohon yang lain. Kemampuan untuk memodifikasi blok mana pun akan setara dengan merusak {i>hash<i} kriptografi. Lihat diagram berikut untuk mengetahui penggambaran struktur ini.

tabel hash dm-verity

Gambar 1. Tabel hash dm-verity

Kunci publik disertakan pada partisi {i>boot<i}, yang harus diverifikasi secara eksternal oleh produsen perangkat. Kunci tersebut digunakan untuk memverifikasi tanda tangan untuk {i>hash<i} itu dan mengkonfirmasi bahwa partisi sistem perangkat telah dilindungi dan tidak berubah.

Operasi

Perlindungan dm-verity ada di {i>kernel<i}. Jadi, jika software rooting membahayakan sistem sebelum kernel muncul, software tersebut akan mempertahankan akses tersebut. Untuk memitigasi hal ini sebagian besar produsen memverifikasi {i>kernel<i} menggunakan kunci yang dibakar ke dalam perangkat. Kunci tersebut tidak dapat diubah setelah perangkat keluar dari pabrik.

Produsen menggunakan kunci tersebut untuk memverifikasi tanda tangan di level pertama yang pada gilirannya memverifikasi tanda tangan pada level berikutnya, {i>bootloader<i} aplikasi dan akhirnya {i>kernel<i}. Setiap produsen ingin memanfaatkan teknik terverifikasi booting harus memiliki metode untuk memverifikasi integritas kernel. Dengan asumsi bahwa {i>kernel<i} telah diverifikasi, {i>kernel<i} dapat melihat perangkat blok dan memverifikasinya saat terpasang.

Salah satu cara memverifikasi perangkat blok adalah dengan langsung melakukan hashing pada kontennya dan membandingkannya dengan nilai yang disimpan. Namun, upaya untuk memverifikasi seluruh perangkat blok dapat memerlukan waktu yang lama dan menghabiskan banyak daya perangkat. Perangkat akan memerlukan waktu yang lama untuk melakukan booting, lalu daya baterainya akan habis secara signifikan sebelum digunakan.

Sebagai gantinya, dm-verity memverifikasi blok satu per satu dan hanya saat setiap blok diakses. Saat dibaca ke dalam memori, blok di-hash secara paralel. Hash kemudian diverifikasi ke atas hierarki. Selain itu, karena membaca blok adalah operasi yang sangat mahal, latensi yang diperkenalkan oleh verifikasi tingkat blok ini relatif nominal.

Jika verifikasi gagal, perangkat akan membuat pesan {i>error<i} I/O yang menunjukkan adanya blok tidak dapat dibaca. Tampaknya sistem file telah rusak, sebagaimana adanya yang diharapkan.

Aplikasi dapat memilih untuk melanjutkan tanpa data yang dihasilkan, seperti saat hasil tersebut tidak diperlukan untuk fungsi utama aplikasi. Namun, jika aplikasi tidak dapat dilanjutkan tanpa data, aplikasi akan gagal.

Teruskan koreksi error

Android 7.0 dan yang lebih baru meningkatkan keandalan dm-verity dengan forward error correction (FEC). Penerapan AOSP dimulai dengan kode perbaikan error Reed-Solomon umum dan menerapkan teknik yang disebut interleaving untuk mengurangi overhead ruang dan meningkatkan jumlah blok yang rusak yang dapat dipulihkan. Untuk mengetahui detail selengkapnya tentang FEC, lihat Booting Terverifikasi yang Diberlakukan Secara Ketat dengan Koreksi Error.

Implementasi

Ringkasan

  1. Buat image sistem ext4.
  2. Buat hierarki hash untuk gambar tersebut.
  3. Buat tabel dm-verity untuk hierarki hash tersebut.
  4. Tanda tangani tabel dm-verity tersebut untuk menghasilkan tanda tangan tabel.
  5. Memaketkan tanda tangan tabel dan tabel dm-verity ke dalam {i>metadata <i}benar.
  6. Gabungkan image sistem, metadata verity, dan hierarki hash.

Lihat Project Chromium - Verified Boot untuk deskripsi mendetail tentang hierarki hash dan tabel dm-verity.

Membuat hierarki hash

Seperti yang dijelaskan dalam pengantar, hierarki hash merupakan bagian integral dari dm-verity. Tujuan alat cryptsetup menghasilkan pohon {i>hash <i}untuk Anda. Atau, yang kompatibel ditentukan di sini:

<your block device name> <your block device name> <block size> <block size> <image size in blocks> <image size in blocks + 8> <root hash> <salt>

Untuk membentuk {i>hash<i}, {i>image<i} sistem dibagi pada lapisan 0 menjadi blok 4k, masing-masing diberi {i>hash<i} SHA256. Lapisan 1 dibentuk dengan menggabungkan hash SHA256 tersebut menjadi blok 4k, sehingga menghasilkan gambar yang jauh lebih kecil. Lapisan 2 terbentuk secara identik, dengan {i>hash<i} SHA256 di Lapisan 1.

Hal ini dilakukan hingga hash SHA256 dari lapisan sebelumnya dapat muat dalam satu blok. Saat mendapatkan SHA256 dari blok tersebut, Anda memiliki hash root hierarki.

Ukuran hierarki hash (dan penggunaan kapasitas {i>disk<i} yang sesuai) bervariasi menurut ukuran partisi yang diverifikasi. Dalam praktiknya, ukuran hierarki hash cenderung kecil, sering kali kurang dari 30 MB.

Jika Anda memiliki blok di lapisan yang tidak terisi sepenuhnya secara alami oleh hash lapisan sebelumnya, Anda harus mengisinya dengan nol untuk mencapai 4k yang diharapkan. Hal ini memungkinkan Anda mengetahui bahwa hierarki hash belum dihapus dan sebagai gantinya diisi dengan data kosong.

Untuk membuat hierarki hash, gabungkan hash lapisan 2 ke hash untuk lapisan 1, hash lapisan 3 ke hash lapisan 2, dan seterusnya. Tulis semua ini ke disk. Perhatikan bahwa ini tidak mereferensikan lapisan 0 hash root.

Sebagai rangkuman, algoritma umum untuk membuat hierarki hash adalah sebagai berikut:

  1. Pilih salt acak (encoding heksadesimal).
  2. Uraikan image sistem Anda menjadi blok 4k.
  3. Untuk setiap blok, dapatkan hash SHA256 (asin).
  4. Gabungkan hash ini untuk membentuk level
  5. Tambahkan level dengan 0 hingga batas blok 4k.
  6. Gabungkan tingkat ke hierarki hash Anda.
  7. Ulangi langkah 2-6 menggunakan level sebelumnya sebagai sumber untuk level berikutnya hingga Anda hanya memiliki satu hash.

Hasilnya adalah satu hash, yang merupakan hash root Anda. Hal ini dan salt Anda digunakan selama pembuatan tabel pemetaan dm-verity.

Membuat tabel pemetaan dm-verity

Bangun tabel pemetaan dm-verity, yang mengidentifikasi perangkat blok (atau target) untuk {i>kernel<i} dan lokasi {i>hash tree<i} (yang merupakan nilai yang sama.) Ini pemetaan digunakan untuk pembuatan dan booting fstab. Tabel tersebut juga mengidentifikasi ukuran blok dan {i>hash_start<i}, lokasi awal hierarki {i>hash<i} (khususnya, nomor bloknya dari awal gambar).

Lihat cryptsetup untuk deskripsi terperinci tentang kolom tabel pemetaan target kebenaran.

Menandatangani tabel dm-verity

Tanda tangani tabel dm-verity untuk menghasilkan tanda tangan tabel. Saat memverifikasi , tanda tangan tabel divalidasi terlebih dahulu. Hal ini dilakukan terhadap kunci di image {i>booting<i} Anda di lokasi yang tetap. Kunci biasanya disertakan dalam sistem build produsen untuk penyertaan otomatis di perangkat di lokasi tetap.

Untuk memverifikasi partisi dengan kombinasi tanda tangan dan tombol ini:

  1. Tambahkan kunci RSA-2048 dalam format yang kompatibel dengan libmincrypt ke partisi /boot di /verity_key. Identifikasi lokasi kunci yang digunakan untuk memverifikasi hash tree.
  2. Di fstab untuk entri yang relevan, tambahkan verify ke flag fs_mgr.

Memaketkan tanda tangan tabel ke dalam metadata

Gabungkan tanda tangan tabel dan tabel dm-verity ke dalam metadata verity. Seluruh blok metadata memiliki beberapa versi sehingga dapat diperpanjang, seperti menambahkan tanda tangan atau mengubah urutannya.

Sebagai pemeriksaan kesehatan, angka ajaib dikaitkan dengan setiap set metadata tabel yang membantu mengidentifikasi tabel. Karena panjangnya disertakan dalam header image sistem ext4, hal ini memberikan cara untuk menelusuri metadata tanpa mengetahui konten data itu sendiri.

Hal ini memastikan Anda tidak memilih untuk memverifikasi partisi yang belum diverifikasi. Jika demikian, tidak adanya angka ajaib ini akan menghentikan proses verifikasi. Angka ini menyerupai 0xb001b001.

Nilai byte dalam hex adalah:

  • byte pertama = b0
  • byte kedua = 01
  • byte ketiga = b0
  • byte keempat = 01

Diagram berikut menggambarkan perincian metadata verifikasi:

<magic number>|<version>|<signature>|<table length>|<table>|<padding>
\-------------------------------------------------------------------/
\----------------------------------------------------------/   |
                            |                                  |
                            |                                 32K
                       block content

Dan tabel ini menjelaskan kolom metadata tersebut.

Tabel 1. Memverifikasi kolom metadata

Kolom Tujuan Ukuran Nilai
angka ajaib digunakan oleh fs_mgr sebagai pemeriksaan keandalan 4 byte 0xb001b001
version digunakan untuk membuat versi blok metadata 4 byte saat ini 0
tanda tangan tanda tangan tabel dalam bentuk padding PKCS1.5 256 byte
panjang tabel panjang tabel dm-verity dalam byte 4 byte
meja tabel {i>dm-verity<i} yang dijelaskan sebelumnya byte panjang tabel
padding struktur ini ditambahkan 0 hingga panjangnya 32 ribu 0

Mengoptimalkan dm-verity

Untuk mendapatkan performa terbaik dari dm-verity, Anda harus:

  • Di kernel, aktifkan NEON SHA-2 untuk ARMv7 dan ekstensi SHA-2 untuk ARMv8.
  • Bereksperimen dengan berbagai read-ahead dan fetch_cluster khusus untuk menemukan konfigurasi terbaik bagi perangkat Anda.