คีย์ห่อด้วยฮาร์ดแวร์

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

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

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

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

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

ออกแบบ

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

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

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

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

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

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

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

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

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

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

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

ลำดับชั้นของคีย์ FBE (พร้อมคีย์ที่ห่อด้วยฮาร์ดแวร์)
รูปที่ 2 ลำดับชั้นของคีย์ FBE (พร้อมคีย์ที่หุ้มด้วยฮาร์ดแวร์)

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

  • หนึ่งอินเทอร์เฟซเพื่อรับ inline_encryption_key และตั้งโปรแกรมลงในช่องคีย์ของเครื่องมือเข้ารหัสแบบอินไลน์โดยตรง ซึ่งช่วยให้สามารถเข้ารหัส/ถอดรหัสเนื้อหาไฟล์ได้โดยไม่ต้องใช้ซอฟต์แวร์ที่เข้าถึงคีย์ดิบ ในเคอร์เนลทั่วไปของ Android อินเทอร์เฟซนี้สอดคล้องกับการดำเนินการ blk_crypto_ll_ops::keyslot_program ซึ่งจะต้องดำเนินการโดยไดรเวอร์หน่วยเก็บข้อมูล
  • อินเทอร์เฟซเดียวเพื่อรับและส่งกลับ sw_secret ("ความลับของซอฟต์แวร์" - เรียกอีกอย่างว่า "ความลับดิบ" ในบางสถานที่) ซึ่งเป็นคีย์ที่ Linux ใช้ในการรับคีย์ย่อยสำหรับทุกอย่างนอกเหนือจากการเข้ารหัสเนื้อหาไฟล์ ในเคอร์เนลทั่วไปของ Android อินเทอร์เฟซนี้สอดคล้องกับการดำเนินการ blk_crypto_ll_ops::derive_sw_secret ซึ่งต้องดำเนินการโดยไดรเวอร์หน่วยเก็บข้อมูล

ในการรับ inline_encryption_key และ sw_secret จากคีย์หน่วยเก็บข้อมูลดิบ ฮาร์ดแวร์ต้องใช้ KDF ที่แข็งแกร่งในการเข้ารหัส KDF นี้ต้องปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในการเข้ารหัส จะต้องมีความปลอดภัยอย่างน้อย 256 บิต นั่นคือเพียงพอสำหรับอัลกอริทึมใดๆ ที่ใช้ในภายหลัง นอกจากนี้ยังต้องใช้ป้ายชื่อ บริบท และ/หรือสตริงข้อมูลเฉพาะแอปพลิเคชันที่แตกต่างกันเมื่อได้รับคีย์ย่อยแต่ละประเภท เพื่อรับประกันว่าคีย์ย่อยที่เป็นผลลัพธ์จะถูกแยกด้วยการเข้ารหัส กล่าวคือ ความรู้ของคีย์ย่อยใดคีย์หนึ่งจะไม่เปิดเผยคีย์ย่อยอื่นๆ ไม่จำเป็นต้องยืดคีย์ เนื่องจากคีย์หน่วยเก็บข้อมูลดิบเป็นคีย์สุ่มที่สม่ำเสมออยู่แล้ว

ในทางเทคนิคแล้ว สามารถใช้ KDF ที่ตรงตามข้อกำหนดด้านความปลอดภัยได้ อย่างไรก็ตาม เพื่อวัตถุประสงค์ในการทดสอบ จำเป็นต้องติดตั้ง KDF เดิมอีกครั้งในโค้ดทดสอบ ขณะนี้ KDF หนึ่งรายการได้รับการตรวจสอบและดำเนินการแล้ว สามารถพบได้ใน ซอร์สโค้ดสำหรับ vts_kernel_encryption_test ขอแนะนำให้ฮาร์ดแวร์ใช้ KDF นี้ ซึ่งใช้ NIST SP 800-108 "KDF in Counter Mode" กับ AES-256-CMAC เป็น PRF โปรดทราบว่าเพื่อให้เข้ากันได้ ทุกส่วนของอัลกอริทึมต้องเหมือนกัน รวมถึงตัวเลือกบริบทและป้ายกำกับ KDF สำหรับแต่ละคีย์ย่อย

การพันกุญแจ

เพื่อให้บรรลุเป้าหมายด้านความปลอดภัยของคีย์ที่ห่อหุ้มด้วยฮาร์ดแวร์ จึงมีการกำหนดการห่อหุ้มคีย์ไว้สองประเภท:

  • การ ห่อชั่วคราว : ฮาร์ดแวร์เข้ารหัสคีย์ดิบโดยใช้คีย์ซึ่งสร้างขึ้นแบบสุ่มทุกครั้งที่บู๊ตและไม่ถูกเปิดเผยโดยตรงจากภายนอกฮาร์ดแวร์
  • การห่อข้อมูลระยะยาว : ฮาร์ดแวร์เข้ารหัสคีย์ดิบโดยใช้คีย์ถาวรที่ไม่ซ้ำกันซึ่งมีอยู่ในฮาร์ดแวร์ซึ่งจะไม่เปิดเผยโดยตรงจากภายนอกฮาร์ดแวร์

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

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

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

  • อินเทอร์เฟซสำหรับสร้างและนำเข้าคีย์หน่วยเก็บข้อมูล ส่งคืนในรูปแบบรวมระยะยาว อินเทอร์เฟซเหล่านี้เข้าถึงได้ทางอ้อมผ่าน KeyMint และสอดคล้องกับแท็ก TAG_STORAGE_KEY KeyMint ความสามารถ "สร้าง" ถูกใช้โดย vold เพื่อสร้างคีย์หน่วยเก็บข้อมูลใหม่สำหรับใช้งานโดย Android ในขณะที่ความสามารถ "นำเข้า" ถูกใช้โดย vts_kernel_encryption_test เพื่อนำเข้าคีย์ทดสอบ
  • อินเทอร์เฟซสำหรับแปลงคีย์หน่วยเก็บข้อมูลแบบรวมระยะยาวเป็นคีย์หน่วยเก็บข้อมูลแบบชั่วคราว ซึ่งสอดคล้องกับเมธอดของ ConvertStorageKeyToEphemeral convertStorageKeyToEphemeral วิธีนี้ใช้โดยทั้ง vold และ vts_kernel_encryption_test เพื่อปลดล็อกที่เก็บข้อมูล

อัลกอริทึมการห่อคีย์คือรายละเอียดการใช้งาน แต่ควรใช้ AEAD ที่แข็งแกร่ง เช่น AES-256-GCM พร้อม IV แบบสุ่ม

ต้องมีการเปลี่ยนแปลงซอฟต์แวร์

AOSP มีเฟรมเวิร์กพื้นฐานสำหรับรองรับคีย์ที่ห่อด้วยฮาร์ดแวร์อยู่แล้ว ซึ่งรวมถึงการสนับสนุนในคอมโพเนนต์ userspace เช่น 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 สำหรับรายละเอียดเพิ่มเติม โปรดดู เอกสารประกอบการเข้ารหัสข้อมูลเมตา