กุญแจหุ้มฮาร์ดแวร์

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

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

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

หมายเหตุ: เครื่องมือเข้ารหัสแบบ inline (หรือ inline ฮาร์ดแวร์การเข้ารหัส) หมายถึงฮาร์ดแวร์ที่เข้ารหัส/ถอดรหัสข้อมูล และกำลังเดินทางไปยัง/จากอุปกรณ์จัดเก็บข้อมูล โดยปกติแล้วจะเป็นโฮสต์ UFS หรือ eMMC ซึ่งใช้ส่วนขยายคริปโตที่กำหนดโดย ข้อมูลจำเพาะของ JEDEC

การออกแบบ

ส่วนนี้จะแสดงดีไซน์ของฟีเจอร์คีย์ที่ห่อด้วยฮาร์ดแวร์ ซึ่งรวมถึง ต้องมีการสนับสนุนฮาร์ดแวร์อะไรบ้าง การสนทนานี้มุ่งเน้นไปที่การเข้ารหัสตามไฟล์ (FBE) แต่ วิธีใช้โซลูชันกับข้อมูลเมตา การเข้ารหัสได้ด้วย

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

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

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

ลำดับชั้นของคีย์

คีย์อาจดึงมาจากคีย์อื่นๆ โดยใช้ KDF (ฟังก์ชันคีย์ดึง) เช่น HKDF, ส่งผลให้เกิดลำดับชั้นคีย์

แผนภาพต่อไปนี้แสดงลำดับชั้นคีย์ทั่วไปสำหรับ FBE ระบบจะไม่ใช้คีย์ที่ปกปิดด้วยฮาร์ดแวร์ในกรณีต่อไปนี้

วันที่ ลำดับชั้นคีย์ FBE (มาตรฐาน)
รูปที่ 1 ลำดับชั้นคีย์ FBE (มาตรฐาน)

คีย์คลาส FBE คือคีย์การเข้ารหัสดิบที่ Android ส่งไปยัง Linux เคอร์เนลเพื่อปลดล็อกชุดไดเรกทอรีที่เข้ารหัสโดยเฉพาะ เช่น ที่เก็บข้อมูลที่เข้ารหัสข้อมูลเข้าสู่ระบบสำหรับผู้ใช้ Android บางราย (ในเคอร์เนล เรียกว่าคีย์ต้นแบบ fscrypt) จากคีย์นี้ เคอร์เนลจะดึงข้อมูล คีย์ย่อยต่อไปนี้

  • ตัวระบุคีย์ ไม่ได้ใช้สำหรับการเข้ารหัส แต่เป็นค่า ใช้เพื่อระบุคีย์ที่ไฟล์หรือไดเรกทอรี ได้รับการปกป้องแล้ว
  • คีย์การเข้ารหัสเนื้อหาไฟล์
  • คีย์การเข้ารหัสชื่อไฟล์

ในทางตรงกันข้าม แผนภาพต่อไปนี้แสดงลำดับชั้นคีย์สำหรับ FBE คีย์ที่ห่อด้วยฮาร์ดแวร์จะใช้ในข้อใด

วันที่ ลำดับชั้นคีย์ FBE (พร้อมคีย์ที่ห่อด้วยฮาร์ดแวร์)
รูปที่ 2 ลำดับชั้นคีย์ 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 โฆษณาระยะยาว

ในการรองรับการจัดการคีย์ที่รวมอยู่ในทั้งสองวิธีนี้ ฮาร์ดแวร์จะต้อง ใช้อินเทอร์เฟซต่อไปนี้

  • อินเทอร์เฟซสำหรับสร้างและนำเข้าคีย์พื้นที่เก็บข้อมูล แล้วแสดงผลคีย์ดังกล่าว รูปแบบห่อหุ้มระยะยาว อินเทอร์เฟซเหล่านี้สามารถเข้าถึงได้โดยอ้อมผ่านทาง KeyMint และสอดคล้องกับแท็ก KeyMint TAG_STORAGE_KEY "สร้าง" 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: เพิ่มแฟล็ก wrappedkey_v0 ใน พารามิเตอร์ fileencryption ตัวอย่างเช่น ให้ใช้ fileencryption=::inlinecrypt_optimized+wrappedkey_v0 สำหรับ โปรดดูรายละเอียดเพิ่มเติมที่ FBE เอกสารประกอบ
  • การเข้ารหัสข้อมูลเมตา: เพิ่มแฟล็ก wrappedkey_v0 ลงใน พารามิเตอร์ metadata_encryption ตัวอย่างเช่น ให้ใช้ metadata_encryption=:wrappedkey_v0 ดูรายละเอียดเพิ่มเติมได้ที่ ข้อมูลเมตา ในเอกสารประกอบเรื่องการเข้ารหัส