กำลังดำเนินการ dm-verity

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

Android 4.4 และสูงกว่ารองรับ Verified Boot ผ่านฟีเจอร์เคอร์เนล device-mapper-verity (dm-verity) ที่เป็นตัวเลือก ซึ่งให้การตรวจสอบความสมบูรณ์ของอุปกรณ์บล็อกอย่างโปร่งใส dm-verity ช่วยป้องกันรูทคิทแบบถาวรที่สามารถยึดสิทธิ์ของรูทและอุปกรณ์ประนีประนอม คุณลักษณะนี้ช่วยให้ผู้ใช้ Android มั่นใจได้ว่าเมื่อบูตอุปกรณ์จะอยู่ในสถานะเดียวกับเมื่อใช้งานครั้งล่าสุด

แอปพลิเคชันที่อาจเป็นอันตราย (PHA) ที่มีสิทธิ์ของรูทสามารถซ่อนจากโปรแกรมตรวจจับและปิดบังตัวเองได้ ซอฟต์แวร์การรูทสามารถทำได้เพราะมักจะได้รับสิทธิพิเศษมากกว่าตัวตรวจจับ ทำให้ซอฟต์แวร์สามารถ "โกหก" กับโปรแกรมตรวจจับได้

คุณลักษณะ dm-verity ช่วยให้คุณดูอุปกรณ์บล็อก เลเยอร์หน่วยเก็บข้อมูลพื้นฐานของระบบไฟล์ และพิจารณาว่าตรงกับการกำหนดค่าที่คาดไว้หรือไม่ มันทำสิ่งนี้โดยใช้ต้นไม้แฮชเข้ารหัส สำหรับทุกบล็อก (โดยทั่วไปคือ 4k) จะมีแฮช SHA256

เนื่องจากค่าแฮชถูกเก็บไว้ในแผนผังของหน้า เฉพาะแฮช "รูท" ระดับบนสุดเท่านั้นที่น่าเชื่อถือเพื่อตรวจสอบส่วนที่เหลือของทรี ความสามารถในการแก้ไขบล็อกใด ๆ จะเทียบเท่ากับการทำลายแฮชการเข้ารหัส ดูแผนภาพต่อไปนี้สำหรับการพรรณนาถึงโครงสร้างนี้

dm-verity-hash-table

รูปที่ 1. ตารางแฮช dm-verity

คีย์สาธารณะรวมอยู่ในพาร์ติชันสำหรับเริ่มระบบ ซึ่งต้องได้รับการตรวจสอบจากภายนอกโดยผู้ผลิตอุปกรณ์ คีย์นั้นใช้เพื่อตรวจสอบลายเซ็นสำหรับแฮชนั้นและยืนยันว่าพาร์ติชั่นระบบของอุปกรณ์ได้รับการป้องกันและไม่เปลี่ยนแปลง

การดำเนินการ

การป้องกัน dm-verity อาศัยอยู่ในเคอร์เนล ดังนั้นหากซอฟต์แวร์การรูททำให้ระบบประนีประนอมก่อนที่เคอร์เนลจะขึ้นมา มันจะคงการเข้าถึงนั้นไว้ เพื่อลดความเสี่ยงนี้ ผู้ผลิตส่วนใหญ่ตรวจสอบเคอร์เนลโดยใช้คีย์ที่เขียนลงในอุปกรณ์ คีย์นั้นไม่สามารถเปลี่ยนแปลงได้เมื่ออุปกรณ์ออกจากโรงงาน

ผู้ผลิตใช้คีย์นั้นเพื่อตรวจสอบลายเซ็นบน bootloader ระดับแรก ซึ่งจะตรวจสอบลายเซ็นในระดับต่อมา โปรแกรม bootloader และเคอร์เนลในท้ายที่สุด ผู้ผลิตแต่ละรายที่ต้องการใช้ประโยชน์จากการ บูตที่ตรวจสอบแล้ว ควรมีวิธีการตรวจสอบความสมบูรณ์ของเคอร์เนล สมมติว่าเคอร์เนลได้รับการตรวจสอบแล้ว เคอร์เนลสามารถดูอุปกรณ์บล็อกและยืนยันได้ขณะติดตั้ง

วิธีหนึ่งในการตรวจสอบอุปกรณ์บล็อกคือการแฮชเนื้อหาโดยตรงและเปรียบเทียบกับค่าที่เก็บไว้ อย่างไรก็ตาม การพยายามตรวจสอบอุปกรณ์บล็อกทั้งหมดอาจใช้เวลานานขึ้นและใช้พลังงานของอุปกรณ์มาก อุปกรณ์จะใช้เวลานานในการบู๊ตและจากนั้นจะระบายออกอย่างมากก่อนใช้งาน

แต่ dm-verity จะตรวจสอบบล็อกทีละรายการและเฉพาะเมื่อเข้าถึงแต่ละบล็อกเท่านั้น เมื่ออ่านในหน่วยความจำ บล็อกจะถูกแฮชแบบขนาน จากนั้นแฮชจะถูกตรวจสอบต้นไม้ และเนื่องจากการอ่านบล็อกเป็นการดำเนินการที่มีราคาแพง ดังนั้นเวลาแฝงที่แนะนำโดยการตรวจสอบระดับบล็อกนี้จึงถือว่าค่อนข้างน้อย

หากการตรวจสอบล้มเหลว อุปกรณ์จะสร้างข้อผิดพลาด I/O โดยระบุว่าไม่สามารถอ่านบล็อกได้ จะปรากฏขึ้นราวกับว่าระบบไฟล์เสียหายตามที่คาดไว้

แอปพลิเคชันอาจเลือกที่จะดำเนินการต่อโดยไม่มีข้อมูลผลลัพธ์ เช่น เมื่อไม่จำเป็นต้องใช้ผลลัพธ์เหล่านั้นในฟังก์ชันหลักของแอปพลิเคชัน อย่างไรก็ตาม หากแอปพลิเคชันไม่สามารถดำเนินการต่อได้โดยไม่มีข้อมูล แอปพลิเคชันจะล้มเหลว

ส่งต่อการแก้ไขข้อผิดพลาด

Android 7.0 ขึ้นไปปรับปรุงความทนทาน dm-verity ด้วยการแก้ไขข้อผิดพลาดไปข้างหน้า (FEC) การใช้งาน AOSP เริ่มต้นด้วยโค้ดแก้ไขข้อผิดพลาดทั่วไปของ Reed-Solomon และใช้เทคนิคที่เรียกว่า interleaving เพื่อลดโอเวอร์เฮดของพื้นที่และเพิ่มจำนวนบล็อกที่เสียหายซึ่งสามารถกู้คืนได้ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ FEC โปรดดูที่ Strictly Enforced Verified Boot with Error Correction

การดำเนินการ

สรุป

  1. สร้างอิมเมจระบบ ext4
  2. สร้าง hash tree สำหรับรูปภาพนั้น
  3. สร้างตาราง dm-verity สำหรับแฮชทรีนั้น
  4. ลงชื่อในตาราง dm-verity นั้นเพื่อสร้างลายเซ็นตาราง
  5. รวมตารางลายเซ็น และตาราง dm-verity ลงในข้อมูลเมตาของ verity
  6. เชื่อมต่ออิมเมจระบบ ข้อมูลเมตา verity และแผนผังแฮช

ดูโครงการ Chromium - Verified Boot สำหรับคำอธิบายโดยละเอียดของแผนผังแฮชและตาราง dm-verity

กำลังสร้างต้นไม้แฮช

ตามที่อธิบายไว้ในบทนำ แผนผังแฮชเป็นส่วนสำคัญของ dm-verity เครื่องมือ cryptsetup จะสร้าง hash tree ให้กับคุณ อีกวิธีหนึ่งคือการกำหนดค่าที่เข้ากันได้ที่นี่:

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

ในการสร้างแฮช อิมเมจระบบจะถูกแบ่งที่เลเยอร์ 0 เป็นบล็อก 4k โดยแต่ละบล็อกจะกำหนดแฮช SHA256 เลเยอร์ 1 เกิดขึ้นจากการรวมแฮช SHA256 เหล่านั้นลงในบล็อก 4k เท่านั้น ส่งผลให้รูปภาพมีขนาดเล็กลงมาก เลเยอร์ 2 ถูกสร้างขึ้นเหมือนกันด้วยแฮช SHA256 ของเลเยอร์ 1

การดำเนินการนี้จะทำจนกว่าแฮช SHA256 ของเลเยอร์ก่อนหน้าจะใส่ลงในบล็อกเดียวได้ เมื่อได้รับ SHA256 ของบล็อกนั้น คุณจะมีรูทแฮชของต้นไม้

ขนาดของแผนผังแฮช (และการใช้พื้นที่ดิสก์ที่เกี่ยวข้อง) จะแตกต่างกันไปตามขนาดของพาร์ติชันที่ตรวจสอบแล้ว ในทางปฏิบัติ ขนาดของ hash tree มักจะมีขนาดเล็ก ซึ่งมักจะน้อยกว่า 30 MB

หากคุณมีบล็อกในเลเยอร์ที่ไม่มีการเติมเต็มตามธรรมชาติโดยแฮชของเลเยอร์ก่อนหน้า คุณควรเพิ่มศูนย์ด้วยศูนย์เพื่อให้ได้ 4k ที่คาดหวัง วิธีนี้ช่วยให้คุณทราบได้ว่าแฮชทรีไม่ได้ถูกลบออก และจะเติมข้อมูลว่างให้สมบูรณ์แทน

ในการสร้าง hash tree ให้เชื่อมแฮชของเลเยอร์ 2 เข้ากับเลเยอร์ที่ 1, เลเยอร์ 3 แฮชเข้ากับเลเยอร์ 2 และอื่นๆ เขียนทั้งหมดนี้ลงในดิสก์ โปรดทราบว่าสิ่งนี้ไม่ได้อ้างอิงเลเยอร์ 0 ของแฮชรูท

ในการสรุป อัลกอริทึมทั่วไปในการสร้าง hash tree มีดังนี้:

  1. เลือกเกลือแบบสุ่ม (การเข้ารหัสฐานสิบหก)
  2. แยกอิมเมจระบบของคุณออกเป็นบล็อก 4k
  3. สำหรับแต่ละบล็อก รับแฮช SHA256 (เค็ม)
  4. เชื่อมแฮชเหล่านี้เพื่อสร้างระดับ
  5. แพดระดับด้วย 0s ถึงขอบบล็อก 4k
  6. เชื่อมต่อระดับกับต้นไม้แฮชของคุณ
  7. ทำซ้ำขั้นตอนที่ 2-6 โดยใช้ระดับก่อนหน้าเป็นแหล่งที่มาของระดับถัดไป จนกว่าคุณจะมีแฮชเพียงอันเดียว

ผลลัพธ์ที่ได้คือแฮชเดียว ซึ่งเป็นแฮชรูทของคุณ สิ่งนี้และเกลือของคุณถูกใช้ระหว่างการสร้างตารางการแมป dm-verity ของคุณ

การสร้างตารางการแมป dm-verity

สร้างตารางการแมป dm-verity ซึ่งระบุอุปกรณ์บล็อก (หรือเป้าหมาย) สำหรับเคอร์เนลและตำแหน่งของแผนผังแฮช (ซึ่งเป็นค่าเดียวกัน) การแมปนี้ใช้สำหรับการสร้างและบูต fstab ตารางยังระบุขนาดของบล็อกและ hash_start ซึ่งเป็นตำแหน่งเริ่มต้นของแผนผังแฮช (โดยเฉพาะหมายเลขบล็อกจากจุดเริ่มต้นของรูปภาพ)

ดู cryptsetup สำหรับคำอธิบายโดยละเอียดของฟิลด์ตารางการแมปเป้าหมายตามความเป็นจริง

ลงนามในตาราง dm-verity

ลงนามในตาราง dm-verity เพื่อสร้างลายเซ็นตาราง เมื่อตรวจสอบพาร์ติชัน ลายเซ็นตารางจะได้รับการตรวจสอบก่อน สิ่งนี้ทำกับคีย์บนอิมเมจสำหรับบูตของคุณในตำแหน่งคงที่ โดยทั่วไปแล้ว คีย์จะรวมอยู่ในระบบการสร้างของผู้ผลิตเพื่อรวมไว้ในอุปกรณ์ในตำแหน่งที่แน่นอนโดยอัตโนมัติ

ในการตรวจสอบพาร์ติชันด้วยลายเซ็นและคีย์ผสมนี้:

  1. เพิ่มคีย์ RSA-2048 ในรูปแบบที่เข้ากันได้กับ libmincrypt ให้กับพาร์ติชัน /boot ที่ /verity_key ระบุตำแหน่งของคีย์ที่ใช้ตรวจสอบแผนผังแฮช
  2. ใน fstab สำหรับรายการที่เกี่ยวข้อง ให้เพิ่มการ verify ไปที่แฟล็ fs_mgr

การรวมลายเซ็นตารางเข้ากับข้อมูลเมตา

รวมตารางลายเซ็นและตาราง dm-verity ลงในข้อมูลเมตาของ verity บล็อกข้อมูลเมตาทั้งหมดมีการกำหนดเวอร์ชันเพื่อให้สามารถขยายได้ เช่น การเพิ่มลายเซ็นประเภทที่สองหรือเปลี่ยนลำดับบางอย่าง

เพื่อตรวจสอบสุขภาพจิต หมายเลขวิเศษจะเชื่อมโยงกับชุดข้อมูลเมตาของตารางแต่ละชุดที่ช่วยระบุตาราง เนื่องจากความยาวรวมอยู่ในส่วนหัวของอิมเมจระบบ ext4 จึงให้วิธีการค้นหาข้อมูลเมตาโดยไม่ทราบเนื้อหาของข้อมูลเอง

เพื่อให้แน่ใจว่าคุณไม่ได้เลือกตรวจสอบพาร์ติชันที่ไม่ผ่านการตรวจสอบ หากไม่มีหมายเลขวิเศษนี้ จะหยุดกระบวนการตรวจสอบ ตัวเลขนี้คล้ายกับ:
0xb001b001

ค่าไบต์ในฐานสิบหกคือ:

  • ไบต์แรก = b0
  • ไบต์ที่สอง = 01
  • ไบต์ที่สาม = b0
  • ไบต์ที่สี่ = 01

ไดอะแกรมต่อไปนี้แสดงรายละเอียดของข้อมูลเมตาที่เป็นจริง:

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

และตารางนี้อธิบายฟิลด์ข้อมูลเมตาเหล่านั้น

ตารางที่ 1. ฟิลด์ข้อมูลเมตาของ Verity

สนาม วัตถุประสงค์ ขนาด ค่า
เลขวิเศษ ใช้โดย fs_mgr เพื่อตรวจสุขภาพจิต 4 ไบต์ 0xb001b001
รุ่น ใช้เพื่อกำหนดเวอร์ชันบล็อกข้อมูลเมตา 4 ไบต์ ปัจจุบัน0
ลายเซ็น ลายเซ็นของตารางในรูปแบบเบาะ PKCS1.5 256 ไบต์
ความยาวของโต๊ะ ความยาวของตาราง dm-verity เป็นไบต์ 4 ไบต์
โต๊ะ ตาราง dm-verity ที่อธิบายไว้ก่อนหน้านี้ ไบต์ความยาวตาราง
การขยายความ โครงสร้างนี้มีความยาวเบาะ 0 ถึง 32k 0

เพิ่มประสิทธิภาพ dm-verity

เพื่อให้ได้ประสิทธิภาพที่ดีที่สุดจาก dm-verity คุณควร:

  • ในเคอร์เนล เปิด NEON SHA-2 สำหรับ ARMv7 และส่วนขยาย SHA-2 สำหรับ ARMv8
  • ทดลองกับการตั้งค่า read-ahead และ prefetch_cluster แบบต่างๆ เพื่อค้นหาการกำหนดค่าที่ดีที่สุดสำหรับอุปกรณ์ของคุณ