การผูกเวอร์ชัน

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

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

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

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

การเปลี่ยนแปลงของฮาล

เพื่อรองรับการผูกเวอร์ชันและการรับรองเวอร์ชัน 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 คือปีที่มีตัวเลขสี่หลัก และ MM คือเดือนที่มีตัวเลขสองหลัก เช่น มีนาคม 2016 จะแสดงเป็น 201603

อัพเกรดคีย์

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

คีย์มาสเตอร์ 3

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

คีย์มาสเตอร์ 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 เป็นพารามิเตอร์เอาต์พุต ใช้เพื่อส่งคืนคีย์ Blob ใหม่

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

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

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

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

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

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

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 และวิธีการคีย์มาสเตอร์อื่นๆ ทั้งหมดจะส่งคืน ErrorCode::KEYMASTER_NOT_CONFIGURED ต่อไป หากข้อมูลตรงกัน ให้ configure ค่าส่งคืน ErrorCode::OK และวิธีการคีย์มาสเตอร์อื่นๆ จะเริ่มทำงานตามปกติ

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

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