สถาปัตยกรรมการรับรองในอุปกรณ์

ตั้งแต่ Android 12 เป็นต้นไป โมดูล Android Runtime (ART) เป็นโมดูล Mainline การอัปเดตโมดูลอาจต้องสร้างอาร์ติแฟกต์การคอมไพล์ล่วงหน้า (AOT) ของไฟล์ JAR ใน Bootclasspath และเซิร์ฟเวอร์ระบบใหม่ เนื่องจากอาร์ติแฟกต์เหล่านี้มีความละเอียดอ่อนด้านความปลอดภัย Android 12 จึงใช้ฟีเจอร์ที่เรียกว่าการลงนามในอุปกรณ์เพื่อ ป้องกันไม่ให้อาร์ติแฟกต์เหล่านี้ถูกดัดแปลง หน้านี้ครอบคลุมสถาปัตยกรรมการลงนามในอุปกรณ์และการโต้ตอบกับฟีเจอร์ความปลอดภัยอื่นๆ ของ Android

การออกแบบระดับสูง

การลงนามในอุปกรณ์มีองค์ประกอบหลัก 2 อย่าง ได้แก่

  • odrefresh เป็นส่วนหนึ่งของโมดูล ART Mainline ซึ่งมีหน้าที่ สร้างอาร์ติแฟกต์รันไทม์ โดยจะตรวจสอบอาร์ติแฟกต์ที่มีอยู่กับ โมดูล ART เวอร์ชันที่ติดตั้ง, ไฟล์ JAR ของ Bootclasspath และไฟล์ JAR ของเซิร์ฟเวอร์ระบบ เพื่อพิจารณาว่าอาร์ติแฟกต์เป็นเวอร์ชันล่าสุดหรือต้องสร้างใหม่ หากต้องสร้างใหม่ odrefresh จะสร้างและจัดเก็บรหัสเหล่านั้น

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

ในกรณีที่เกิดข้อผิดพลาด เช่น เมื่อค่าแฮชของไฟล์ไม่ตรงกัน odrefresh และ odsign จะทิ้งอาร์ติแฟกต์ที่มีอยู่ทั้งหมดใน /data และ พยายามสร้างอาร์ติแฟกต์ขึ้นมาใหม่ หากไม่สำเร็จ ระบบจะกลับไปใช้โหมด JIT

odrefresh และ odsign ได้รับการปกป้องโดย dm-verity และเป็นส่วนหนึ่งของ ห่วงโซ่การเปิดเครื่องที่ได้รับการยืนยันของ Android

การคำนวณข้อมูลสรุปของไฟล์ด้วย fs-verity

fs-verity เป็นฟีเจอร์ของเคอร์เนล Linux ที่ทำการยืนยันข้อมูลไฟล์ตามโครงสร้างต้นไม้ Merkle การเปิดใช้ fs-verity ในไฟล์จะทําให้ระบบไฟล์ สร้างต้นไม้ Merkle เหนือข้อมูลของไฟล์โดยใช้แฮช SHA-256 จัดเก็บไว้ใน ตําแหน่งที่ซ่อนอยู่ข้างไฟล์ และทําเครื่องหมายไฟล์เป็นแบบอ่านอย่างเดียว fs-verity จะตรวจสอบข้อมูลของไฟล์กับต้นไม้ Merkle โดยอัตโนมัติตามต้องการเมื่อมีการ อ่าน fs-verity จะทําให้แฮชรูทของต้นไม้ Merkle พร้อมใช้งานเป็นค่าที่เรียกว่าสรุปไฟล์ fs-verity และ fs-verity จะตรวจสอบว่าข้อมูลใดก็ตามที่อ่าน จากไฟล์สอดคล้องกับสรุปไฟล์นี้

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

ในอุปกรณ์ที่เคอร์เนลไม่รองรับ fs-verity odsign จะกลับไปใช้ การคำนวณข้อมูลสรุปของไฟล์ในพื้นที่ผู้ใช้ odsignใช้อัลกอริทึมแฮชที่อิงตาม Merkle Tree เดียวกันกับ fs-verity ดังนั้นค่าแฮชจึงเหมือนกันในทั้ง 2 กรณี อุปกรณ์ทั้งหมดที่เปิดตัวด้วย Android 11 ขึ้นไปต้องใช้ fs-verity

การจัดเก็บข้อมูลสรุปของไฟล์

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

การยืนยันค่าแฮชของไฟล์

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

คีย์การลงชื่อที่เชื่อถือได้

Android 12 เปิดตัวฟีเจอร์ใหม่ของ Keystore ที่เรียกว่า คีย์ระยะการบูต ซึ่งจะช่วยแก้ไขข้อกังวลด้านความปลอดภัยต่อไปนี้

  • อะไรที่ป้องกันไม่ให้ผู้โจมตีใช้คีย์การลงนามของเราเพื่อลงนามในodsign.infoเวอร์ชันของตนเอง
  • อะไรที่ป้องกันไม่ให้ผู้โจมตีสร้างคีย์ Signing ของตนเองและใช้คีย์นั้นเพื่อลงนามใน odsign.info เวอร์ชันของตนเอง

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

ระดับขั้นตอนการบูตจะมีหมายเลขตั้งแต่ 0 ถึงหมายเลขวิเศษ 1000000000 ในระหว่างกระบวนการบูตของ Android คุณสามารถเพิ่มระดับการบูตได้โดยการตั้งค่าพร็อพเพอร์ตี้ของระบบจาก init.rc ตัวอย่างเช่น โค้ดต่อไปนี้จะตั้งค่าระดับการบูตเป็น 10

setprop keystore.boot_level 10

ไคลเอ็นต์ของ Keystore สามารถสร้างคีย์ที่เชื่อมโยงกับระดับการบูตที่เฉพาะเจาะจงได้ เช่น หากคุณสร้างคีย์สำหรับระดับการบูต 10 คีย์นั้นจะใช้ได้ก็ต่อเมื่ออุปกรณ์อยู่ในระดับการบูต 10 เท่านั้น

odsign ใช้ระดับการบูต 30 และคีย์การลงนามที่สร้างจะเชื่อมโยงกับระดับการบูตนั้น ก่อนใช้คีย์เพื่อลงนามในอาร์ติแฟกต์ odsign จะยืนยันว่าคีย์เชื่อมโยงกับระดับการบูต 30

ซึ่งจะป้องกันการโจมตี 2 รูปแบบที่อธิบายไว้ก่อนหน้านี้ในส่วนนี้

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

Keystore ช่วยให้มั่นใจได้ว่ามีการบังคับใช้ระดับการบูตอย่างเหมาะสม ส่วนต่อไปนี้จะอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับวิธีดำเนินการนี้สำหรับ KeyMint (เดิมคือ Keymaster) เวอร์ชันต่างๆ

การติดตั้งใช้งาน Keymaster 4.0

Keymaster เวอร์ชันต่างๆ จะจัดการการใช้งานคีย์ในระยะการบูต แตกต่างกัน ในอุปกรณ์ที่มี TEE/StrongBox Keymaster 4.0 Keymaster จะจัดการ การติดตั้งใช้งานดังนี้

  1. ในการบูตครั้งแรก Keystore จะสร้างคีย์แบบสมมาตร K0 โดยมีMAX_USES_PER_BOOTแท็กตั้งค่าเป็น 1 ซึ่งหมายความว่าคีย์จะใช้ได้เพียงครั้งเดียวต่อการบูต
  2. ในระหว่างการบูต หากมีการเพิ่มระดับการบูต ระบบจะสร้างคีย์ใหม่สำหรับระดับการบูตนั้นจาก K0 โดยใช้ฟังก์ชัน HKDF: Ki+i=HKDF(Ki, "some_fixed_string") เช่น หากคุณย้ายจากระดับการบูต 0 ไปยังระดับการบูต 10 ระบบจะเรียกใช้ HKDF 10 ครั้งเพื่อสร้าง K10 จาก K0
  3. เมื่อระดับการบูตเปลี่ยนไป ระบบจะลบคีย์สำหรับระดับการบูตก่อนหน้า ออกจากหน่วยความจำ และคีย์ที่เชื่อมโยงกับระดับการบูตก่อนหน้าจะ ใช้ไม่ได้อีกต่อไป

    คีย์ K0 คือคีย์ MAX_USES_PER_BOOT=1 ซึ่งหมายความว่าคุณจะใช้คีย์นั้นในภายหลังเมื่อบูตไม่ได้ด้วย เนื่องจากจะมีการเปลี่ยนระดับการบูตอย่างน้อย 1 ครั้ง (เป็นการเปลี่ยนไปที่ระดับการบูตสุดท้าย) เสมอ

เมื่อไคลเอ็นต์ Keystore เช่น odsign ขอให้สร้างคีย์ในระดับการบูต i ระบบจะเข้ารหัส Blob ด้วยคีย์ Ki เนื่องจาก Ki ไม่พร้อมใช้งาน หลังจากระดับการบูต i จึงไม่สามารถสร้างหรือถอดรหัสคีย์นี้ในขั้นตอนการบูต ในภายหลังได้

การใช้งาน Keymaster 4.1 และ KeyMint 1.0

การติดตั้งใช้งาน Keymaster 4.1 และ KeyMint 1.0 ส่วนใหญ่จะเหมือนกับการติดตั้งใช้งาน Keymaster 4.0 ความแตกต่างหลักคือ K0 ไม่ใช่คีย์ MAX_USES_PER_BOOT แต่เป็นคีย์ EARLY_BOOT_ONLY ซึ่งเปิดตัวใน Keymaster 4.1 EARLY_BOOT_ONLY คีย์จะใช้ได้ในช่วงแรกๆ ของการ บูตเท่านั้น เมื่อไม่มีโค้ดที่ไม่น่าเชื่อถือทำงานอยู่ ซึ่งจะช่วยเพิ่มระดับการป้องกันอีกขั้น โดยในการใช้งาน Keymaster 4.0 ผู้โจมตีที่บุกรุกระบบไฟล์และ SELinux จะแก้ไขฐานข้อมูล Keystore เพื่อสร้างMAX_USES_PER_BOOT=1คีย์ของตนเองเพื่อใช้ลงนามในอาร์ติแฟกต์ได้ การโจมตีดังกล่าวเป็นไปไม่ได้ ด้วยการติดตั้งใช้งาน Keymaster 4.1 และ KeyMint 1.0 เนื่องจากEARLY_BOOT_ONLYสร้างคีย์ได้ในระหว่างการบูตช่วงแรกเท่านั้น

คอมโพเนนต์สาธารณะของคีย์การลงชื่อที่เชื่อถือได้

odsign ดึงข้อมูลคอมโพเนนต์คีย์สาธารณะของคีย์การลงนามจากคีย์สโตร์ อย่างไรก็ตาม Keystore จะไม่เรียกคีย์สาธารณะดังกล่าวจาก TEE/SE ที่มี คีย์ส่วนตัวที่เกี่ยวข้อง แต่จะดึงคีย์สาธารณะจากฐานข้อมูลในดิสก์ของตัวเองแทน ซึ่งหมายความว่าผู้โจมตีที่บุกรุกระบบไฟล์ สามารถแก้ไขฐานข้อมูลคีย์สโตร์ให้มีคีย์สาธารณะซึ่งเป็นส่วนหนึ่ง ของคู่คีย์สาธารณะ/ส่วนตัวภายใต้การควบคุมของตนได้

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