การเชื่อมโยงเวอร์ชัน

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

เพื่อรองรับโครงสร้างโมดูลของ Treble และยกเลิกการเชื่อมโยง system.img กับ boot.img Keymaster 4 ได้เปลี่ยนรูปแบบการเชื่อมโยงเวอร์ชันคีย์ให้มีระดับการแก้ไขแยกกันสำหรับแต่ละพาร์ติชัน วิธีนี้ช่วยให้สามารถอัปเดตพาร์ติชันแต่ละรายการได้อิสระ ทั้งยังให้การปกป้องการย้อนกลับด้วย

ใน Android 9 พาร์ติชัน boot, system และ vendor จะมีระดับแพตช์เป็นของตัวเอง

  • อุปกรณ์ที่มี Android Verified Boot (AVB) สามารถใส่ระดับแพตช์ทั้งหมดและเวอร์ชันของระบบไว้ใน vbmeta เพื่อให้ Bootloader มอบข้อมูลดังกล่าวให้ Keymaster ได้ สำหรับพาร์ติชันที่ลิงก์ ข้อมูลเวอร์ชันของพาร์ติชันจะอยู่ใน vbmeta ที่ลิงก์ โดยทั่วไป ข้อมูลเวอร์ชันควรอยู่ใน vbmeta struct ที่มีข้อมูลการยืนยัน (แฮชหรือแฮชทรี) สําหรับพาร์ติชันหนึ่งๆ
  • ในอุปกรณ์ที่ไม่มี AVB
    • การติดตั้งใช้งานการบูตที่ยืนยันแล้วต้องระบุแฮชของข้อมูลเมตาเวอร์ชันให้กับ Bootloader เพื่อให้ Bootloader ระบุแฮชให้กับ Keymaster ได้
    • boot.img จัดเก็บระดับแพตช์ในส่วนหัวต่อไปได้
    • system.img จะจัดเก็บระดับแพตช์และเวอร์ชันระบบปฏิบัติการในพร็อพเพอร์ตี้แบบอ่านอย่างเดียวต่อไปได้
    • vendor.img จัดเก็บระดับแพตช์ในพร็อพเพอร์ตี้ที่อ่านอย่างเดียว ro.vendor.build.version.security_patch
    • บูตโหลดเดอร์สามารถส่งแฮชของข้อมูลทั้งหมดที่ตรวจสอบโดยบูตที่ยืนยันแล้วให้กับ Keymaster
  • ใน Android 9 ให้ใช้แท็กต่อไปนี้เพื่อระบุข้อมูลเวอร์ชันสำหรับพาร์ติชันต่อไปนี้
    • VENDOR_PATCH_LEVEL: พาร์ติชัน vendor
    • BOOT_PATCH_LEVEL: พาร์ติชัน boot
    • OS_PATCH_LEVEL และ OS_VERSION: การแบ่งพาร์ติชัน system (OS_VERSION ถูกนำออกจากส่วนหัว boot.img
  • การติดตั้งใช้งาน Keymaster ควรจัดการระดับแพตช์ทั้งหมดแยกกัน คีย์จะใช้งานได้หากข้อมูลเวอร์ชันทั้งหมดตรงกับค่าที่เชื่อมโยงกับคีย์ และIKeymaster::upgradeDevice()จะเปลี่ยนไปใช้แพตช์ระดับที่สูงขึ้นหากจําเป็น

การเปลี่ยนแปลง HAL

Android 7.1 เพิ่มแท็ก Tag::OS_VERSION และ Tag::OS_PATCHLEVEL รวมถึงเมธอด configure และ upgradeKey เพื่อรองรับการเชื่อมโยงเวอร์ชันและการรับรองเวอร์ชัน แท็กเวอร์ชันจะเพิ่มโดยอัตโนมัติจากการติดตั้งใช้งาน Keymaster 2 ขึ้นไปลงในคีย์ที่สร้างขึ้นใหม่ (หรืออัปเดต) ทั้งหมด นอกจากนี้ ระบบจะปฏิเสธการใช้คีย์ที่ไม่มีเวอร์ชันหรือระดับแพตช์ของระบบปฏิบัติการที่ตรงกับเวอร์ชันหรือระดับแพตช์ของระบบปฏิบัติการปัจจุบันตามลำดับด้วย ErrorCode::KEY_REQUIRES_UPGRADE

Tag::OS_VERSION คือค่า UINT ที่แสดงถึงส่วนเวอร์ชันหลัก เวอร์ชันย่อย และเวอร์ชันย่อยย่อยของระบบ Android เป็น MMmmss โดยที่ MM คือเวอร์ชันหลัก mm คือเวอร์ชันย่อย และ ss คือเวอร์ชันย่อยย่อย เช่น 6.1.2 จะแสดงเป็น 060102

Tag::OS_PATCHLEVEL คือค่า UINT ที่แสดงปีและเดือนของการอัปเดตระบบครั้งล่าสุดในรูปแบบ YYYYMM โดย YYYY คือปี 4 หลัก และ MM คือเดือน 2 หลัก เช่น เดือนมีนาคม 2016 จะแสดงเป็น 201603

UpgradeKey

Android 7.1 ได้เพิ่มเมธอด upgradeKey ลงใน HAL เพื่อให้สามารถอัปเกรดคีย์เป็นเวอร์ชันระบบปฏิบัติการและระดับแพตช์ใหม่ของภาพระบบได้ ดังนี้

Keymaster 3

    upgradeKey(vec keyBlobToUpgrade, vec upgradeParams)
        generates(ErrorCode error, vec upgradedKeyBlob);

Keymaster 2

keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev,
    const keymaster_key_blob_t* key_to_upgrade,
    const keymaster_key_param_set_t* upgrade_params,
    keymaster_key_blob_t* upgraded_key);
  • dev คือโครงสร้างอุปกรณ์
  • keyBlobToUpgrade คือคีย์ที่ต้องอัปเกรด
  • upgradeParams คือพารามิเตอร์ที่จําเป็นสําหรับการอัปเกรดคีย์ ซึ่งรวมถึง Tag::APPLICATION_ID และ Tag::APPLICATION_DATA ซึ่งจําเป็นต่อการถอดรหัสบล็อกคีย์ หากระบุไว้ในระหว่างการสร้าง
  • upgradedKeyBlob คือพารามิเตอร์เอาต์พุตที่ใช้เพื่อแสดงผลบล็อกคีย์ใหม่

หากเรียก upgradeKey ด้วย Blob ของคีย์ที่ไม่สามารถแยกวิเคราะห์ได้หรือไม่ถูกต้อง ระบบจะแสดงผล ErrorCode::INVALID_KEY_BLOB หากเรียกใช้ด้วยคีย์ที่มีระดับแพตช์มากกว่าค่าปัจจุบันของระบบ ระบบจะแสดงผล ErrorCode::INVALID_ARGUMENT หากเรียกใช้ด้วยคีย์ที่มีเวอร์ชันระบบปฏิบัติการมากกว่าค่าปัจจุบันของระบบ และค่าของระบบไม่ใช่ 0 ระบบจะแสดงผล ErrorCode::INVALID_ARGUMENT เวอร์ชันระบบปฏิบัติการ ระบบอนุญาตให้อัปเกรดจากค่าที่ไม่ใช่ 0 เป็น 0 ได้ ในกรณีที่มีข้อผิดพลาดในการติดต่อสื่อสารกับโลกที่ปลอดภัย ระบบจะแสดงผลค่าข้อผิดพลาดที่เหมาะสม (เช่น ErrorCode::SECURE_HW_ACCESS_DENIED, ErrorCode::SECURE_HW_BUSY) มิเช่นนั้น ระบบจะแสดงผล ErrorCode::OK และแสดงผล Blob ของคีย์ใหม่ใน upgradedKeyBlob

keyBlobToUpgrade จะยังคงใช้งานได้หลังจากupgradeKeyโทร และในทางทฤษฎีแล้วอาจใช้ซ้ำได้หากมีการดาวน์เกรดอุปกรณ์ ในทางปฏิบัติ โดยทั่วไปแล้วคีย์สโตร์จะเรียก deleteKey ในบล็อก keyBlobToUpgrade ไม่นานหลังจากที่เรียก upgradeKey หาก keyBlobToUpgrade มีแท็ก Tag::ROLLBACK_RESISTANT upgradedKeyBlob ก็ควรมีแท็กนั้นด้วย (และควรป้องกันการย้อนกลับ)

การกำหนดค่าที่ปลอดภัย

หากต้องการใช้การเชื่อมโยงเวอร์ชัน TA ของ Keymaster ต้องมีวิธีรับเวอร์ชันปัจจุบันของระบบปฏิบัติการและระดับแพตช์ (ข้อมูลเวอร์ชัน) อย่างปลอดภัย และตรวจสอบว่าข้อมูลที่รับนั้นตรงกับข้อมูลเกี่ยวกับระบบที่ทำงานอยู่

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

นอกจากนี้ คุณต้องตรวจสอบว่าอิมเมจระบบมีข้อมูลเวอร์ชันเดียวกับอิมเมจบูต ด้วยเหตุนี้ เราจึงเพิ่มเมธอดกำหนดค่าลงใน HAL ของ Keymaster ดังนี้

keymaster_error_t (*configure)(const struct keymaster2_device* dev,
  const keymaster_key_param_set_t* params);

อาร์กิวเมนต์ params มี Tag::OS_VERSION และ Tag::OS_PATCHLEVEL ลูกค้า Keymaster2 จะเรียกใช้เมธอดนี้หลังจากเปิด HAL แต่ก่อนเรียกใช้เมธอดอื่นๆ หากมีการเรียกใช้เมธอดอื่นก่อนการกําหนดค่า TA จะแสดงErrorCode::KEYMASTER_NOT_CONFIGURED

เมื่อเรียก configure เป็นครั้งแรกหลังจากอุปกรณ์บูต ระบบควรตรวจสอบว่าข้อมูลเวอร์ชันที่ระบุตรงกับข้อมูล bootloader ระบุไว้ หากข้อมูลเวอร์ชันไม่ตรงกัน configure จะแสดงผลเป็น ErrorCode::INVALID_ARGUMENT และเมธอด Keymaster อื่นๆ ทั้งหมดจะแสดงผลเป็น ErrorCode::KEYMASTER_NOT_CONFIGURED ต่อไป หากข้อมูลตรงกัน configure จะแสดงผลเป็น ErrorCode::OK และเมธอดอื่นๆ ของ Keymaster จะเริ่มทํางานตามปกติ

การเรียกใช้ configure ครั้งต่อๆ ไปจะแสดงผลค่าเดียวกันกับที่การเรียกใช้ครั้งแรกแสดง และจะไม่เปลี่ยนสถานะของ Keymaster

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