Menerapkan dm-verity

Android 4.4 dan lebih tinggi mendukung Boot Terverifikasi melalui fitur kernel opsional device-mapper-verity (dm-verity), yang menyediakan pemeriksaan integritas transparan dari perangkat blok. dm-verity membantu mencegah rootkit persisten yang dapat menahan hak akses root dan membahayakan perangkat. Fitur ini membantu pengguna Android memastikan saat mem-boot perangkat dalam keadaan yang sama seperti saat terakhir digunakan.

Aplikasi yang Berpotensi Membahayakan (PHA) dengan hak akses root dapat bersembunyi dari program deteksi dan menutupi dirinya sendiri. Perangkat lunak rooting dapat melakukan ini karena seringkali lebih istimewa daripada detektor, memungkinkan perangkat lunak untuk "berbohong" ke program deteksi.

Fitur dm-verity memungkinkan Anda melihat perangkat blok, lapisan penyimpanan yang mendasari sistem file, dan menentukan apakah itu cocok dengan konfigurasi yang diharapkan. Ini dilakukan dengan menggunakan pohon hash kriptografis. Untuk setiap blok (biasanya 4k), ada hash SHA256.

Karena nilai hash disimpan di pohon halaman, hanya hash "root" tingkat atas yang harus dipercaya untuk memverifikasi sisa pohon. Kemampuan untuk memodifikasi salah satu blok akan sama dengan memecahkan hash kriptografi. Lihat diagram berikut untuk penggambaran struktur ini.

dm-verity-hash-tabel

Gambar 1. tabel hash dm-verity

Kunci publik disertakan pada partisi boot, yang harus diverifikasi secara eksternal oleh produsen perangkat. Kunci itu digunakan untuk memverifikasi tanda tangan untuk hash itu dan mengonfirmasi bahwa partisi sistem perangkat dilindungi dan tidak berubah.

Operasi

perlindungan dm-verity tinggal di kernel. Jadi jika perangkat lunak rooting membahayakan sistem sebelum kernel muncul, itu akan mempertahankan akses itu. Untuk mengurangi risiko ini, sebagian besar produsen memverifikasi kernel menggunakan kunci yang dibakar ke dalam perangkat. Kunci itu tidak dapat diubah setelah perangkat meninggalkan pabrik.

Produsen menggunakan kunci itu untuk memverifikasi tanda tangan pada bootloader tingkat pertama, yang pada gilirannya memverifikasi tanda tangan pada tingkat berikutnya, bootloader aplikasi dan akhirnya kernel. Setiap pabrikan yang ingin memanfaatkan boot terverifikasi harus memiliki metode untuk memverifikasi integritas kernel. Dengan asumsi kernel telah diverifikasi, kernel dapat melihat perangkat blok dan memverifikasinya saat dipasang.

Salah satu cara untuk memverifikasi perangkat blok adalah dengan langsung hash isinya dan membandingkannya dengan nilai yang tersimpan. Namun, mencoba memverifikasi seluruh perangkat blok dapat memakan waktu lama dan menghabiskan banyak daya perangkat. Perangkat akan membutuhkan waktu lama untuk boot dan kemudian terkuras secara signifikan sebelum digunakan.

Sebaliknya, dm-verity memverifikasi blok secara individual dan hanya ketika masing-masing diakses. Saat dibaca ke dalam memori, blok di-hash secara paralel. Hash kemudian diverifikasi ke atas pohon. Dan karena membaca blok adalah operasi yang mahal, latensi yang diperkenalkan oleh verifikasi tingkat blok ini relatif nominal.

Jika verifikasi gagal, perangkat menghasilkan kesalahan I/O yang menunjukkan bahwa blok tidak dapat dibaca. Ini akan muncul seolah-olah sistem file telah rusak, seperti 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 melanjutkan tanpa data, itu akan gagal.

Koreksi kesalahan maju

Android 7.0 dan yang lebih tinggi meningkatkan ketahanan dm-verity dengan koreksi kesalahan maju (FEC). Implementasi AOSP dimulai dengan kode koreksi kesalahan umum Reed-Solomon dan menerapkan teknik yang disebut interleaving untuk mengurangi overhead ruang dan meningkatkan jumlah blok rusak yang dapat dipulihkan. Untuk detail selengkapnya tentang FEC, lihat Boot Terverifikasi yang Diberlakukan dengan Ketat dengan Koreksi Kesalahan .

Penerapan

Ringkasan

  1. Menghasilkan gambar sistem ext4.
  2. Hasilkan pohon hash untuk gambar itu.
  3. Buat tabel dm-verity untuk pohon hash itu.
  4. Tandatangani tabel dm-verity untuk menghasilkan tanda tangan tabel.
  5. Bundel tanda tangan tabel dan tabel dm-verity ke dalam metadata verity.
  6. Menggabungkan citra sistem, metadata verity, dan pohon hash.

LihatProyek Chromium - Boot Terverifikasi untuk deskripsi rinci tentang pohon hash dan tabel dm-verity.

Menghasilkan pohon hash

Seperti yang dijelaskan dalam pendahuluan, pohon hash merupakan bagian integral dari dm-verity. Alat cryptsetup akan menghasilkan pohon hash untuk Anda. Atau, yang kompatibel didefinisikan 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 hash, citra sistem dipecah pada lapisan 0 menjadi 4k blok, masing-masing diberi hash SHA256. Layer 1 dibentuk dengan menggabungkan hanya hash SHA256 ke dalam blok 4k, menghasilkan gambar yang jauh lebih kecil. Layer 2 dibentuk secara identik, dengan hash SHA256 dari Layer 1.

Ini dilakukan sampai hash SHA256 dari lapisan sebelumnya dapat ditampung dalam satu blok. Saat mendapatkan SHA256 dari blok itu, Anda memiliki hash root dari pohon tersebut.

Ukuran pohon hash (dan penggunaan ruang disk yang sesuai) bervariasi dengan ukuran partisi yang diverifikasi. Dalam praktiknya, ukuran pohon hash cenderung kecil, seringkali kurang dari 30 MB.

Jika Anda memiliki blok di lapisan yang tidak sepenuhnya terisi secara alami oleh hash dari lapisan sebelumnya, Anda harus mengisinya dengan nol untuk mencapai 4k yang diharapkan. Ini memungkinkan Anda mengetahui pohon hash belum dihapus dan malah dilengkapi dengan data kosong.

Untuk menghasilkan pohon hash, gabungkan hash layer 2 ke hash untuk layer 1, layer 3 hash ke layer 2, dan seterusnya. Tulis semua ini ke disk. Perhatikan bahwa ini tidak mereferensikan layer 0 dari hash root.

Untuk rekap, algoritma umum untuk membangun pohon hash adalah sebagai berikut:

  1. Pilih garam acak (pengkodean heksadesimal).
  2. Pisahkan citra sistem Anda menjadi blok 4k.
  3. Untuk setiap blok, dapatkan hash SHA256 (asin).
  4. Gabungkan hash ini untuk membentuk level
  5. Pad level dengan 0s ke batas blok 4k.
  6. Gabungkan level ke pohon hash Anda.
  7. Ulangi langkah 2-6 menggunakan level sebelumnya sebagai sumber untuk level berikutnya hingga Anda hanya memiliki satu hash.

Hasil dari ini adalah hash tunggal, yang merupakan hash root Anda. Ini dan garam Anda digunakan selama konstruksi tabel pemetaan dm-verity Anda.

Membangun tabel pemetaan dm-verity

Buat tabel pemetaan dm-verity, yang mengidentifikasi perangkat blok (atau target) untuk kernel dan lokasi pohon hash (yang merupakan nilai yang sama.) Pemetaan ini digunakan untuk pembuatan dan booting fstab . Tabel juga mengidentifikasi ukuran blok dan hash_start, lokasi awal pohon hash (khususnya, nomor bloknya dari awal gambar).

Lihat cryptsetup untuk deskripsi mendetail tentang bidang tabel pemetaan target verity.

Menandatangani tabel dm-verity

Tandatangani tabel dm-verity untuk menghasilkan tanda tangan tabel. Saat memverifikasi partisi, tanda tangan tabel divalidasi terlebih dahulu. Ini dilakukan terhadap kunci pada gambar boot Anda di lokasi tetap. Kunci biasanya disertakan dalam sistem pembuatan pabrikan untuk penyertaan otomatis pada perangkat di lokasi tetap.

Untuk memverifikasi partisi dengan tanda tangan dan kombinasi 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 pohon hash.
  2. Di fstab untuk entri yang relevan, tambahkan verify ke flag fs_mgr .

Menggabungkan tanda tangan tabel ke dalam metadata

Bundel tanda tangan tabel dan tabel dm-verity ke dalam metadata verity. Seluruh blok metadata diversi sehingga dapat diperpanjang, seperti menambahkan jenis tanda tangan kedua atau mengubah beberapa urutan.

Sebagai pemeriksaan kewarasan, angka ajaib dikaitkan dengan setiap set metadata tabel yang membantu mengidentifikasi tabel. Karena panjangnya disertakan dalam header gambar sistem ext4, ini menyediakan cara untuk mencari metadata tanpa mengetahui isi data itu sendiri.

Ini memastikan Anda belum memilih untuk memverifikasi partisi yang belum diverifikasi. Jika demikian, tidak adanya nomor 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 rincian metadata verity:

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

Dan tabel ini menjelaskan bidang metadata tersebut.

Tabel 1. Bidang metadata verifikasi

Bidang Tujuan Ukuran Nilai
angka ajaib digunakan oleh fs_mgr sebagai pemeriksaan kewarasan 4 byte 0xb001b001
Versi: kapan digunakan untuk versi blok metadata 4 byte saat ini 0
tanda tangan tanda tangan tabel dalam bentuk empuk PKCS1.5 256 byte
panjang meja panjang tabel dm-verity dalam byte 4 byte
meja tabel dm-verity yang dijelaskan sebelumnya byte panjang tabel
lapisan struktur ini 0-empuk hingga 32k panjangnya 0

Mengoptimalkan dm-verity

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

  • Di kernel, aktifkan NEON SHA-2 untuk ARMv7 dan ekstensi SHA-2 untuk ARMv8.
  • Bereksperimenlah dengan pengaturan read-ahead dan prefetch_cluster yang berbeda untuk menemukan konfigurasi terbaik untuk perangkat Anda.