ใช้ DM-verity

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

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

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

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

dm-verity-hash-table

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

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

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

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

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

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

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

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

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

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

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

การใช้งาน

สรุป

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

ดูคำอธิบายโดยละเอียดของ Hash Tree และตาราง dm-verity ได้ที่โครงการ Chromium - การบูตที่ตรวจสอบแล้ว

สร้างแผนผังแฮช

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

<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 ของบล็อกนั้น คุณจะมีแฮชรูทของต้นไม้

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

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

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

โดยสรุปแล้ว อัลกอริทึมทั่วไปในการสร้างแฮชทรีมีดังนี้

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

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

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

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

ดูคำอธิบายโดยละเอียดของช่องตารางการแมปเป้าหมายของ Verity ได้ที่ cryptsetup

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

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

วิธียืนยันพาร์ติชันด้วยลายเซ็นและชุดค่าผสมคีย์นี้

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

รวมลายเซ็นตารางไว้ในข้อมูลเมตา

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

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

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

ค่าไบต์ในเลขฐาน 16 มีดังนี้

  • ไบต์แรก = b0
  • ไบต์ที่ 2 = 01
  • ไบต์ที่ 3 = b0
  • ไบต์ที่ 4 = 01

แผนภาพต่อไปนี้แสดงรายละเอียดของข้อมูลเมตาการตรวจสอบความถูกต้อง

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

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

ตาราง 1 ตรวจสอบช่องข้อมูลเมตา

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

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

คุณควรดําเนินการต่อไปนี้เพื่อให้ได้รับประสิทธิภาพที่ดีที่สุดจากการตรวจสอบโดยตรง

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