การเข้ารหัสพื้นที่เก็บข้อมูลของ Android เช่นเดียวกับซอฟต์แวร์เข้ารหัสดิสก์และไฟล์ส่วนใหญ่ เดิมทีจะใช้คีย์การเข้ารหัสดิบที่อยู่ในหน่วยความจำของระบบ เพื่อให้สามารถดำเนินการเข้ารหัสได้ แม้ว่าจะมีการเข้ารหัส ด้วยฮาร์ดแวร์เฉพาะแทนที่จะเป็นซอฟต์แวร์ จัดการคีย์การเข้ารหัสดิบ
โดยทั่วไปแล้ว ปัญหานี้ไม่ได้ถูกมองว่าเป็นปัญหา เนื่องจากคีย์จะไม่ปรากฏขึ้นในระหว่างการโจมตีแบบออฟไลน์ ซึ่งเป็นประเภทการโจมตีหลักที่การเข้ารหัสพื้นที่เก็บข้อมูลมีไว้เพื่อป้องกัน แต่ก็มีความต้องการที่จะ เพิ่มการป้องกันการโจมตีประเภทอื่นๆ เช่น การเปิดเครื่อง Cold Boot และการโจมตีออนไลน์ที่ผู้โจมตีอาจทําให้ระบบรั่วไหลได้ โดยไม่ทำอันตรายต่ออุปกรณ์โดยสมบูรณ์
Android 11 แก้ปัญหานี้ด้วยการรองรับคีย์ที่รวมไว้ในฮาร์ดแวร์เมื่อมีการรองรับฮาร์ดแวร์ คีย์ที่รวมฮาร์ดแวร์คือคีย์พื้นที่เก็บข้อมูลที่รู้จักในรูปแบบข้อมูลดิบเท่านั้น ฮาร์ดแวร์เฉพาะ ซอฟต์แวร์จะมองเห็นและทำงานกับคีย์เหล่านี้ได้ในการรวม (เข้ารหัสแล้ว) ฮาร์ดแวร์นี้ต้องสามารถสร้างและนําเข้าคีย์พื้นที่เก็บข้อมูล แพ็กเกจคีย์พื้นที่เก็บข้อมูลในรูปแบบชั่วคราวและระยะยาว ดึงข้อมูลคีย์ย่อย โปรแกรมคีย์ย่อย 1 คีย์ลงในเครื่องมือเข้ารหัสในบรรทัดโดยตรง และแสดงผลคีย์ย่อยแยกต่างหากไปยังซอฟต์แวร์
หมายเหตุ: เครื่องมือเข้ารหัสแบบอินไลน์ (หรือฮาร์ดแวร์การเข้ารหัสแบบอินไลน์) หมายถึงฮาร์ดแวร์ที่เข้ารหัส/ถอดรหัสข้อมูลขณะส่งไปยัง/จากอุปกรณ์เก็บข้อมูล โดยปกติแล้วจะเป็นโฮสต์ UFS หรือ eMMC ซึ่งใช้ส่วนขยายคริปโตที่กำหนดโดย ข้อมูลจำเพาะของ JEDEC
การออกแบบ
ส่วนนี้จะแสดงดีไซน์ของฟีเจอร์คีย์ที่ห่อด้วยฮาร์ดแวร์ ซึ่งรวมถึง ต้องมีการสนับสนุนฮาร์ดแวร์อะไรบ้าง การพูดคุยนี้มุ่งเน้นที่การเข้ารหัสตามไฟล์ (FBE) แต่โซลูชันนี้ใช้ได้กับการเข้ารหัสข้อมูลเมตาด้วย
วิธีหนึ่งที่จะหลีกเลี่ยงการใช้คีย์การเข้ารหัสดิบในหน่วยความจำของระบบได้คือ ให้เก็บไว้เฉพาะในช่องคีย์ของเครื่องมือคริปโตแบบอินไลน์ อย่างไรก็ตาม มีปัญหาบางอย่าง เช่น
- จำนวนคีย์การเข้ารหัสอาจมากกว่าจำนวนช่องเก็บคีย์
- เครื่องมือคริปโตแบบอินไลน์สามารถใช้เพื่อเข้ารหัส/ถอดรหัสบล็อกทั้งหมดของ ข้อมูลบนดิสก์ อย่างไรก็ตาม ในกรณีของ FBE ซอฟต์แวร์ยังคงต้องสามารถ ทำงานด้านการเข้ารหัสอื่นๆ เช่น การเข้ารหัสชื่อไฟล์และการดึงคีย์ บางอย่าง ซอฟต์แวร์ยังคงต้องมีสิทธิ์เข้าถึงคีย์ FBE ดิบเพื่อ ทำงานอื่นๆ ด้วย
เพื่อหลีกเลี่ยงปัญหาเหล่านี้ ระบบจะเปลี่ยนคีย์พื้นที่เก็บข้อมูลเป็นคีย์ที่รวมไว้ในฮาร์ดแวร์แทน ซึ่งจะถอดออกและใช้ได้โดยฮาร์ดแวร์เฉพาะเท่านั้น ซึ่งช่วยให้รองรับคีย์ได้ไม่จำกัดจำนวน นอกจากนี้ ระบบจะแก้ไขลําดับชั้นของคีย์และย้ายบางส่วนไปยังฮาร์ดแวร์นี้ ซึ่งจะช่วยให้ส่งคีย์ย่อยกลับไปที่ซอฟต์แวร์สําหรับงานที่ไม่สามารถใช้เครื่องมือเข้ารหัสแบบอินไลน์ได้
ลําดับชั้นของคีย์
คีย์จะมาจากคีย์อื่นๆ ได้โดยใช้ KDF (ฟังก์ชันการสร้างคีย์) เช่น HKDF ซึ่งจะทำให้เกิดลําดับชั้นคีย์
แผนภาพต่อไปนี้แสดงลำดับชั้นคีย์ทั่วไปสำหรับ FBE ระบบจะไม่ใช้คีย์ที่ปกปิดด้วยฮาร์ดแวร์ในกรณีต่อไปนี้
คีย์ระดับ FBE คือคีย์การเข้ารหัสดิบซึ่ง Android ส่งไปยังเคอร์เนล Linux เพื่อปลดล็อกชุดไดเรกทอรีที่เข้ารหัส เช่น พื้นที่เก็บข้อมูลที่เข้ารหัสข้อมูลเข้าสู่ระบบสำหรับผู้ใช้ Android บางราย (ในเคอร์เนล คีย์นี้เรียกว่าคีย์หลัก fscrypt) จากคีย์นี้ เคอร์เนลจะสร้างคีย์ย่อยต่อไปนี้
- ตัวระบุคีย์ ค่านี้ไม่ได้ใช้สำหรับการเข้ารหัส แต่เป็นค่าที่ใช้ระบุคีย์ที่ใช้ปกป้องไฟล์หรือไดเรกทอรีหนึ่งๆ
- คีย์การเข้ารหัสเนื้อหาไฟล์
- คีย์การเข้ารหัสชื่อไฟล์
ในทางตรงกันข้าม แผนภาพต่อไปนี้แสดงลำดับชั้นคีย์สำหรับ FBE คีย์ที่ห่อด้วยฮาร์ดแวร์จะใช้ในข้อใด
เมื่อเทียบกับกรณีก่อนหน้านี้ จะมีการเพิ่มลําดับชั้นอีกระดับลงในลําดับชั้นคีย์ และย้ายคีย์การเข้ารหัสเนื้อหาไฟล์ รูท โหนดยังคงแสดงคีย์ที่ Android ส่งไปยัง Linux เพื่อปลดล็อกชุด ไดเรกทอรีที่เข้ารหัส แต่ตอนนี้คีย์ดังกล่าวอยู่ในรูปแบบที่ปกปิดชั่วคราว และ ในการใช้งานจะต้องส่งไปยังฮาร์ดแวร์เฉพาะ ฮาร์ดแวร์นี้ต้อง ใช้อินเทอร์เฟซ 2 แบบที่ใช้คีย์ที่ปกปิดชั่วคราว:
- อินเทอร์เฟซเดียวสำหรับดึงข้อมูล
inline_encryption_key
โดยตรง วางโปรแกรมไว้ในช่องคีย์ของเครื่องมือคริปโตแบบอินไลน์ การดำเนินการนี้ช่วยให้ไฟล์ เนื้อหาที่จะเข้ารหัส/ถอดรหัสโดยที่ซอฟต์แวร์ไม่สามารถเข้าถึงไฟล์ข้อมูล RAW ในเคอร์เนลทั่วไปของ Android อินเทอร์เฟซนี้จะสอดคล้องกับblk_crypto_ll_ops::keyslot_program
ซึ่งต้อง ด้วยการใช้ไดรเวอร์พื้นที่เก็บข้อมูล - หนึ่งอินเทอร์เฟซสำหรับดึงข้อมูลและแสดงผล
sw_secret
("ซอฟต์แวร์ ความลับ" -- หรือที่เรียกว่า "ข้อมูลลับแบบ RAW" ในบางตำแหน่ง) ซึ่งเป็นกุญแจสำคัญที่ Linux ใช้เพื่อดึงข้อมูลคีย์ย่อยสำหรับทุกอย่างนอกเหนือจากเนื้อหาไฟล์ การเข้ารหัส ในเคอร์เนลทั่วไปของ Android อินเทอร์เฟซนี้จะสอดคล้องกับการดำเนินการblk_crypto_ll_ops::derive_sw_secret
ซึ่งไดรเวอร์พื้นที่เก็บข้อมูลต้องติดตั้งใช้งาน
หากต้องการดึงข้อมูล inline_encryption_key
และ sw_secret
จาก
คีย์พื้นที่เก็บข้อมูลดิบ ฮาร์ดแวร์ต้องใช้ KDF ที่มีการเข้ารหัสที่รัดกุม KDF นี้
ต้องเป็นไปตามแนวทางปฏิบัติแนะนำด้านวิทยาการเข้ารหัส ต้องมีระดับความปลอดภัยที่
อย่างน้อย 256 บิต ซึ่งเพียงพอสำหรับอัลกอริทึมที่ใช้ในภายหลัง นอกจากนี้ ยังต้องใช้สตริงป้ายกำกับ บริบท และข้อมูลเฉพาะแอปที่ต่างกันเมื่อสร้างคีย์ย่อยแต่ละประเภทเพื่อรับประกันว่าคีย์ย่อยที่ได้จะแยกกันทางวิทยาการเข้ารหัส กล่าวคือ ความรู้เกี่ยวกับคีย์ย่อยรายการหนึ่งจะไม่เปิดเผยคีย์ย่อยรายการอื่น ไม่จำเป็นต้องยืดคีย์ เนื่องจากคีย์พื้นที่เก็บข้อมูลดิบเป็นคีย์อยู่แล้ว
คีย์แบบสุ่มแบบเดียวกัน
ในทางเทคนิคแล้ว คุณสามารถใช้ KDF ใดก็ได้ที่เป็นไปตามข้อกำหนดด้านความปลอดภัย
อย่างไรก็ตาม สำหรับการทดสอบ
จำเป็นต้องนำ KDF เดิมมาใช้ซ้ำใน
โค้ดทดสอบ ปัจจุบันมีการตรวจสอบและปรับใช้ KDF 1 รายการ พบได้
ในซอร์สโค้ดสำหรับ vts_kernel_encryption_test
ขอแนะนำให้ฮาร์ดแวร์ใช้ KDF นี้ ซึ่งใช้ NIST SP 800-108 "KDF ในโหมดตัวนับ" ที่มี AES-256-CMAC เป็น PRF โปรดทราบว่าอัลกอริทึมทุกส่วนต้องเหมือนกัน รวมถึงการเลือกบริบท KDF และป้ายกำกับสำหรับคีย์ย่อยแต่ละรายการ จึงจะใช้งานร่วมกันได้
การห่อคีย์
เพื่อให้บรรลุเป้าหมายด้านความปลอดภัยของคีย์ที่ห่อด้วยฮาร์ดแวร์ เราได้รวมคีย์ 2 ประเภท มีคำจำกัดความดังนี้
- การรวมชั่วคราว: ฮาร์ดแวร์เข้ารหัสคีย์ดิบโดยใช้คีย์ ซึ่งจะสร้างแบบสุ่มทุกครั้งที่เปิดเครื่องและไม่เปิดเผย ภายนอกฮาร์ดแวร์
- การรวมระยะยาว: ฮาร์ดแวร์จะเข้ารหัสคีย์ดิบโดยใช้ คีย์ถาวรที่ไม่ซ้ำกันซึ่งมีอยู่ในฮาร์ดแวร์ ซึ่งไม่ใช่ มีการเปิดเผยนอกฮาร์ดแวร์
คีย์ทั้งหมดที่ส่งไปยังเคอร์เนล Linux เพื่อปลดล็อกพื้นที่เก็บข้อมูลจะได้รับการรวมไว้ชั่วคราว ซึ่งทำให้มั่นใจว่าหากผู้โจมตีสามารถแยก คีย์ที่ใช้งานอยู่จากหน่วยความจำของระบบ คีย์นั้นก็จะใช้งานไม่ได้ไม่เพียงแค่ ออกจากอุปกรณ์ แต่ยังอยู่ในอุปกรณ์หลังจากการรีบูต
ในขณะเดียวกัน Android ยังคงต้องจัดเก็บเวอร์ชันที่เข้ารหัสได้ บนดิสก์เพื่อให้ปลดล็อกได้ตั้งแต่แรก ข้อมูล RAW คีย์จะทำงานสำหรับวัตถุประสงค์นี้ อย่างไรก็ตาม คุณไม่ควรทานอาหาร จะอยู่ในหน่วยความจำของระบบเลย เพื่อไม่ให้ระบบดึงข้อมูลคีย์เหล่านั้นออกมา ออกจากอุปกรณ์ แม้ว่าจะดึงข้อมูลเมื่อเปิดเครื่องก็ตาม ด้วยเหตุนี้ แนวคิด ของการ Wrapper โฆษณาระยะยาว
ฮาร์ดแวร์ต้องใช้อินเทอร์เฟซต่อไปนี้เพื่อรองรับการจัดการคีย์ที่รวมไว้ 2 วิธีนี้
- อินเทอร์เฟซสำหรับสร้างและนำเข้าคีย์พื้นที่เก็บข้อมูล แล้วแสดงผลคีย์ดังกล่าว
รูปแบบห่อหุ้มระยะยาว อินเทอร์เฟซเหล่านี้เข้าถึงได้แบบอ้อมผ่าน KeyMint และสอดคล้องกับ
TAG_STORAGE_KEY
แท็ก KeyMint "สร้าง"vold
ใช้ความสามารถนี้เพื่อสร้างพื้นที่เก็บข้อมูลใหม่ สำหรับใช้งานโดย Android ในขณะที่ปุ่ม "นำเข้า" ความสามารถนี้ใช้โดยvts_kernel_encryption_test
เพื่อนำเข้าคีย์ทดสอบ - อินเทอร์เฟซสำหรับแปลงคีย์พื้นที่เก็บข้อมูลแบบรวมระยะยาวเป็น
คีย์พื้นที่เก็บข้อมูลที่ห่อหุ้มชั่วคราว ซึ่งสอดคล้องกับ
convertStorageKeyToEphemeral
เมธอด KeyMint ทั้งvold
และvts_kernel_encryption_test
ใช้วิธีการนี้เพื่อปลดล็อกพื้นที่เก็บข้อมูล
อัลกอริทึมการรวมคีย์เป็นรายละเอียดการติดตั้งใช้งาน แต่ควรใช้แท็ก AEAD สูง เช่น AES-256-GCM ที่มี IV แบบสุ่ม
ต้องมีการเปลี่ยนแปลงซอฟต์แวร์
AOSP มีเฟรมเวิร์กพื้นฐานสำหรับรองรับคีย์ที่ห่อด้วยฮาร์ดแวร์อยู่แล้ว ซึ่งรวมถึงการรองรับในคอมโพเนนต์พื้นที่ผู้ใช้ เช่น vold
ตลอดจนการรองรับเคอร์เนล Linux ใน blk-crypto, fscrypt และ dm-default-key
แต่จำเป็นต้องมีการเปลี่ยนแปลงเฉพาะการติดตั้งใช้งานบางอย่าง
การเปลี่ยนแปลง KeyMint
การติดตั้งใช้งาน KeyMint ของอุปกรณ์ต้องได้รับการแก้ไขให้รองรับ TAG_STORAGE_KEY
และใช้วิธีการ convertStorageKeyToEphemeral
ใน Keymaster มีการใช้ exportKey
แทน
convertStorageKeyToEphemeral
การเปลี่ยนแปลงเคอร์เนลของ Linux
ต้องแก้ไขไดรเวอร์เคอร์เนลของ Linux สำหรับเครื่องมือเข้ารหัสแบบอินไลน์ของอุปกรณ์ เพื่อรองรับคีย์ที่ห่อด้วยฮาร์ดแวร์
สำหรับเคอร์เนล android14
และสูงกว่า
กำหนด BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
ใน blk_crypto_profile::key_types_supported
ทำ blk_crypto_ll_ops::keyslot_program
และblk_crypto_ll_ops::keyslot_evict
รองรับการเขียนโปรแกรม/การนำคีย์ที่ห่อฮาร์ดแวร์ออก
และใช้งาน blk_crypto_ll_ops::derive_sw_secret
สำหรับเคอร์เนล android12
และ android13
ตั้งค่า BLK_CRYPTO_FEATURE_WRAPPED_KEYS
ใน blk_keyslot_manager::features
ทำ blk_ksm_ll_ops::keyslot_program
และ blk_ksm_ll_ops::keyslot_evict
รองรับการเขียนโปรแกรม/การนำคีย์ที่ห่อฮาร์ดแวร์ออก
และใช้งาน blk_ksm_ll_ops::derive_raw_secret
สําหรับเคอร์เนล android11
ให้ตั้งค่า BLK_CRYPTO_FEATURE_WRAPPED_KEYS
ใน keyslot_manager::features
สร้าง keyslot_mgmt_ll_ops::keyslot_program
และ keyslot_mgmt_ll_ops::keyslot_evict
รองรับการเขียนโปรแกรม/การลบคีย์ที่รวมไว้ในฮาร์ดแวร์ และติดตั้งใช้งาน keyslot_mgmt_ll_ops::derive_raw_secret
การทดสอบ
แม้ว่าการเข้ารหัสด้วยคีย์ที่ห่อด้วยฮาร์ดแวร์จะทดสอบได้ยากกว่าการเข้ารหัส
กับคีย์มาตรฐาน คุณจะยังทดสอบได้โดยนำเข้าคีย์ทดสอบและ
โดยนำหลักการสำคัญที่ได้จากฮาร์ดแวร์มาใช้ใหม่ ซึ่งติดตั้งใช้งานใน vts_kernel_encryption_test
หากต้องการทำการทดสอบนี้ ให้ใช้คำสั่งต่อไปนี้
atest -v vts_kernel_encryption_test
อ่านบันทึกการทดสอบและยืนยันว่ากรอบการทดสอบคีย์ที่ปกปิดด้วยฮาร์ดแวร์ (เช่น
FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
และ
DmDefaultKeyTest.TestHwWrappedKey
) ไม่ได้ถูกข้ามเนื่องจากการสนับสนุน
สำหรับคีย์ที่ห่อด้วยฮาร์ดแวร์ ไม่พบ เนื่องจากผลการทดสอบยังคง
"ผ่าน" ในกรณีนั้น
เปิดใช้คีย์
เมื่อการสนับสนุนคีย์ที่ห่อด้วยฮาร์ดแวร์ของอุปกรณ์ทำงานอย่างถูกต้อง คุณสามารถ
ทำการเปลี่ยนแปลงต่อไปนี้ในไฟล์ fstab
ของอุปกรณ์เพื่อทำ
Android จะใช้ FBE และเข้ารหัสข้อมูลเมตาดังนี้
- FBE: เพิ่ม Flag
wrappedkey_v0
ลงในพารามิเตอร์fileencryption
ตัวอย่างเช่น ให้ใช้fileencryption=::inlinecrypt_optimized+wrappedkey_v0
ดูรายละเอียดเพิ่มเติมได้ในเอกสารประกอบของ FBE - การเข้ารหัสข้อมูลเมตา: เพิ่มแฟล็ก
wrappedkey_v0
ลงใน พารามิเตอร์metadata_encryption
ตัวอย่างเช่น ให้ใช้metadata_encryption=:wrappedkey_v0
ดูรายละเอียดเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับการเข้ารหัสข้อมูลเมตา