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

ใน 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 ดังนั้น bootloader สามารถจัดเตรียมให้กับ Keymaster ได้ สำหรับพาร์ติชันที่ถูกล่ามโซ่ ข้อมูลเวอร์ชันสำหรับพาร์ติชันจะอยู่ใน vbmeta ที่ถูกล่ามโซ่ โดยทั่วไป ข้อมูลเวอร์ชันควรอยู่ในโครงสร้าง vbmeta struct ที่มีข้อมูลการตรวจสอบ (hash หรือ hashtree) สำหรับพาร์ติชันที่กำหนด
  • บนอุปกรณ์ที่ไม่มี AVB:
    • การใช้งาน Boot ที่ตรวจสอบแล้วจำเป็นต้องจัดเตรียมแฮชของข้อมูลเมตาเวอร์ชันให้กับ bootloader เพื่อให้ bootloader สามารถจัดเตรียมแฮชให้กับ Keymaster
    • boot.img สามารถจัดเก็บระดับแพตช์ต่อไปในส่วนหัว
    • system.img สามารถจัดเก็บระดับแพตช์และเวอร์ชัน OS ต่อไปในคุณสมบัติแบบอ่านอย่างเดียวได้
    • vendor.img เก็บระดับแพตช์ไว้ในคุณสมบัติอ่านอย่างเดียว ro.vendor.build.version.security_patch
    • โปรแกรมโหลดบูตสามารถจัดเตรียมแฮชของข้อมูลทั้งหมดที่ตรวจสอบแล้วโดยการบูตที่ยืนยันไปยังคีย์มาสเตอร์
  • ใน 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 คือปีที่มีตัวเลขสี่หลัก และ 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 เป็นพารามิเตอร์เอาต์พุต ใช้เพื่อส่งคืนคีย์บล็อบใหม่

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

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

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

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

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

นอกจากนี้ยังจำเป็นต้องตรวจสอบให้แน่ใจว่าอิมเมจระบบมีข้อมูลเวอร์ชันเดียวกันกับอิมเมจสำหรับบูต ด้วยเหตุนี้ วิธีการกำหนดค่าจึงถูกเพิ่มใน keymaster 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 นั้นถูกเรียกเร็วมากในการบู๊ตระบบ จะทำให้หน้าต่างแห่งโอกาสนี้ยากต่อการใช้ประโยชน์