การเข้ารหัสทั้งดิสก์คือกระบวนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดบนอุปกรณ์ Android โดยใช้คีย์เข้ารหัส เมื่อเข้ารหัสอุปกรณ์แล้ว ข้อมูลทั้งหมดที่สร้างโดยผู้ใช้จะถูกเข้ารหัสโดยอัตโนมัติก่อนที่จะส่งไปยังดิสก์ และการอ่านข้อมูลทั้งหมดจะถอดรหัสข้อมูลโดยอัตโนมัติก่อนที่จะส่งคืนไปยังกระบวนการเรียก
การเข้ารหัสทั้งดิสก์ถูกนำมาใช้กับ Android ในเวอร์ชัน 4.4 แต่ Android 5.0 ได้แนะนำคุณลักษณะใหม่เหล่านี้:
- สร้างการเข้ารหัสที่รวดเร็ว ซึ่งจะเข้ารหัสเฉพาะบล็อกที่ใช้แล้วบนพาร์ติชันข้อมูลเพื่อหลีกเลี่ยงการบูตครั้งแรกที่ใช้เวลานาน ขณะนี้ระบบไฟล์ ext4 และ f2fs เท่านั้นที่รองรับการเข้ารหัสที่รวดเร็ว
- เพิ่ม ธงบังคับเข้ารหัส
forceencrypt
เพื่อเข้ารหัสในการบูตครั้งแรก - เพิ่มการรองรับรูปแบบและการเข้ารหัสโดยไม่ต้องใช้รหัสผ่าน
- เพิ่มที่เก็บข้อมูลคีย์เข้ารหัสที่สนับสนุนฮาร์ดแวร์โดยใช้ความสามารถในการลงนามของ Trusted Execution Environment (TEE) (เช่นใน TrustZone) โปรดดูรายละเอียดเพิ่มเติม ในการจัดเก็บคีย์ที่เข้ารหัส
ข้อควรระวัง: อุปกรณ์ที่อัปเกรดเป็น Android 5.0 แล้วเข้ารหัสแล้วอาจกลับสู่สถานะที่ไม่ได้เข้ารหัสโดยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น อุปกรณ์ Android 5.0 ใหม่ที่เข้ารหัสเมื่อบู๊ตครั้งแรกจะไม่สามารถกลับสู่สถานะที่ไม่ได้เข้ารหัสได้
วิธีการทำงานของการเข้ารหัสทั้งดิสก์ของ Android
การเข้ารหัสทั้งดิสก์ของ Android ใช้ dm-crypt
ซึ่งเป็นคุณลักษณะเคอร์เนลที่ทำงานที่ชั้นอุปกรณ์บล็อก ด้วยเหตุนี้ การเข้ารหัสจึงทำงานร่วมกับ Embedded MultiMediaCard ( eMMC) และอุปกรณ์แฟลชที่คล้ายกันซึ่งนำเสนอตัวเองในเคอร์เนลเป็นอุปกรณ์บล็อก ไม่สามารถเข้ารหัสด้วย YAFFS ซึ่งพูดโดยตรงกับชิปแฟลช NAND ดิบ
อัลกอริธึมการเข้ารหัสคือ 128 Advanced Encryption Standard (AES) พร้อมด้วย cipher-block chaining (CBC) และ ESSIV:SHA256 มาสเตอร์คีย์ถูกเข้ารหัสด้วย AES 128 บิตผ่านการเรียกไปยังไลบรารี OpenSSL คุณต้องใช้ 128 บิตขึ้นไปสำหรับคีย์ (โดยที่ 256 เป็นทางเลือก)
หมายเหตุ: OEM สามารถใช้ 128 บิตหรือสูงกว่าเพื่อเข้ารหัสมาสเตอร์คีย์ได้
ในการเปิดตัว Android 5.0 มีสถานะการเข้ารหัสสี่ประเภท:
- ค่าเริ่มต้น
- เข็มหมุด
- รหัสผ่าน
- ลวดลาย
เมื่อบู๊ตครั้งแรก อุปกรณ์จะสร้างมาสเตอร์คีย์ 128 บิตแบบสุ่ม จากนั้นแฮชด้วยรหัสผ่านเริ่มต้นและเกลือที่เก็บไว้ รหัสผ่านเริ่มต้นคือ: "default_password" อย่างไรก็ตาม แฮชผลลัพธ์ยังถูกเซ็นผ่าน TEE (เช่น TrustZone) ซึ่งใช้แฮชของลายเซ็นเพื่อเข้ารหัสคีย์หลัก
คุณสามารถค้นหารหัสผ่านเริ่มต้นที่กำหนดไว้ในไฟล์ cryptfs.cpp ของ Android Open Source Project
เมื่อผู้ใช้ตั้งค่า PIN/รหัสผ่าน หรือรหัสผ่านบนอุปกรณ์ เฉพาะคีย์ 128 บิตเท่านั้นที่จะถูกเข้ารหัสและจัดเก็บซ้ำ (เช่น การเปลี่ยนแปลง PIN/รหัสผ่าน/รูปแบบของผู้ใช้จะไม่ทำให้เกิดการเข้ารหัสซ้ำของข้อมูลผู้ใช้) โปรดทราบว่า อุปกรณ์ที่มีการจัดการ อาจอยู่ภายใต้ข้อจำกัดของ PIN รูปแบบ หรือรหัสผ่าน
การเข้ารหัสถูกจัดการโดย init
และ vold
init
เรียก vold
และ vold ตั้งค่าคุณสมบัติเพื่อทริกเกอร์เหตุการณ์ใน init ส่วนอื่นๆ ของระบบยังดูที่คุณสมบัติเพื่อดำเนินการต่างๆ เช่น สถานะรายงาน ขอรหัสผ่าน หรือแจ้งให้รีเซ็ตเป็นค่าเริ่มต้นจากโรงงานในกรณีที่เกิดข้อผิดพลาดร้ายแรง ในการเรียกใช้คุณสมบัติการเข้ารหัสใน vold
ระบบจะใช้เครื่องมือบรรทัดคำสั่ง vdc
คำสั่ง cryptfs
: checkpw
, restart
, enablecrypto
, changepw
, cryptocomplete
, verifypw
, setfield
, getfield
, mountdefaultencrypted
, getpwtype
, getpw
และ clearpw
ในการเข้ารหัส ถอดรหัส หรือล้าง /data
/data
จะต้องไม่เมาต์ /data อย่างไรก็ตาม เพื่อแสดงส่วนต่อประสานผู้ใช้ (UI) กรอบงานต้องเริ่มทำงานและกรอบงานต้องการ /data
เพื่อเรียกใช้ เพื่อแก้ไขปริศนานี้ ระบบไฟล์ชั่วคราวจะถูกติดตั้งบน /data
ซึ่งช่วยให้ Android สามารถขอรหัสผ่าน แสดงความคืบหน้า หรือแนะนำการล้างข้อมูลได้ตามต้องการ มีข้อจำกัดว่าในการเปลี่ยนจากระบบไฟล์ชั่วคราวเป็นระบบไฟล์ /data
จริง ระบบต้องหยุดทุกกระบวนการที่มีไฟล์เปิดอยู่บนระบบไฟล์ชั่วคราว และรีสตาร์ทกระบวนการเหล่านั้นบนระบบไฟล์ /data
จริง ในการทำเช่นนี้ บริการทั้งหมดต้องอยู่ในกลุ่มใดกลุ่มหนึ่งจากสามกลุ่ม: core
, main
และ late_start
-
core
: อย่าปิดเครื่องหลังจากเริ่มต้น -
main
: ปิดเครื่องแล้วรีสตาร์ทหลังจากป้อนรหัสผ่านของดิสก์ -
late_start
: ไม่เริ่มจนกว่า/data
จะถูกถอดรหัสและติดตั้ง
หากต้องการทริกเกอร์การกระทำเหล่านี้ คุณสมบัติ vold.decrypt
จะถูกตั้งค่าเป็น สตริงต่างๆ หากต้องการหยุดและเริ่มบริการใหม่ init
สั่งเริ่มต้นคือ:
-
class_reset
: หยุดบริการ แต่อนุญาตให้รีสตาร์ทด้วย class_start -
class_start
: เริ่มบริการใหม่ -
class_stop
: หยุดบริการและเพิ่มแฟล็กSVC_DISABLED
บริการที่หยุดทำงานไม่ตอบสนองต่อclass_start
กระแส
มีสี่โฟลว์สำหรับอุปกรณ์ที่เข้ารหัส อุปกรณ์ได้รับการเข้ารหัสเพียงครั้งเดียวจากนั้นทำตามขั้นตอนการบูตตามปกติ
- เข้ารหัสอุปกรณ์ที่ไม่ได้เข้ารหัสก่อนหน้านี้:
- เข้ารหัสอุปกรณ์ใหม่ด้วย
forceencrypt
: การเข้ารหัสบังคับเมื่อบู๊ตครั้งแรก (เริ่มต้นใน Android L) - เข้ารหัสอุปกรณ์ที่มีอยู่: การเข้ารหัสที่เริ่มต้นโดยผู้ใช้ (Android K และรุ่นก่อนหน้า)
- เข้ารหัสอุปกรณ์ใหม่ด้วย
- บูตอุปกรณ์ที่เข้ารหัส:
- การเริ่มอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งไม่ได้ตั้งรหัสผ่าน (เกี่ยวข้องกับอุปกรณ์ที่ใช้ Android 5.0 และใหม่กว่า)
- การเริ่มอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้
นอกจากโฟลว์เหล่านี้แล้ว อุปกรณ์ยังสามารถเข้ารหัสล้มเหลวได้ /data
แต่ละโฟลว์มีคำอธิบายโดยละเอียดด้านล่าง
เข้ารหัสอุปกรณ์ใหม่ด้วยการบังคับเข้ารหัส
นี่เป็นการบู๊ตครั้งแรกตามปกติสำหรับอุปกรณ์ Android 5.0
- ตรวจหาระบบไฟล์ที่ไม่ได้เข้ารหัสด้วยการตั้งค่าสถานะ
forceencrypt
/data
ไม่ได้เข้ารหัส แต่จำเป็นต้องเข้ารหัสเพราะforceencrypt
ใช้การเข้ารหัส ยกเลิกการต่อเชื่อม/data
. - เริ่มการเข้ารหัส
/data
vold.decrypt = "trigger_encryption"
ทริกเกอร์init.rc
ซึ่งจะทำให้vold
เข้ารหัส/data
โดยไม่มีรหัสผ่าน (ไม่มีการตั้งค่าเนื่องจากควรเป็นอุปกรณ์ใหม่) - เมานต์ tmpfs
vold
ติดตั้ง tmpfs/data
(โดยใช้ตัวเลือก tmpfs จากro.crypto.tmpfs_options
) และตั้งค่าคุณสมบัติvold.encrypt_progress
เป็น 0vold
เตรียม tmpfs/data
สำหรับการบูตระบบที่เข้ารหัส และตั้งค่าคุณสมบัติvold.decrypt
เป็น:trigger_restart_min_framework
- นำกรอบการแสดงความคืบหน้า
เนื่องจากอุปกรณ์แทบไม่มีข้อมูลที่จะเข้ารหัส แถบแสดงความคืบหน้ามักจะไม่ปรากฏขึ้นเนื่องจากการเข้ารหัสเกิดขึ้นอย่างรวดเร็ว ดู เข้ารหัสอุปกรณ์ที่มีอยู่ สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ UI ความคืบหน้า
- เมื่อ
/data
ถูกเข้ารหัส ให้ถอดเฟรมเวิร์กออกvold
ตั้งค่าvold.decrypt
เป็นtrigger_default_encryption
ซึ่งเริ่มบริการdefaultcrypto
(ขั้นตอนนี้เริ่มต้นโฟลว์ด้านล่างเพื่อติดตั้งข้อมูลผู้ใช้ที่เข้ารหัสเริ่มต้น)trigger_default_encryption
ตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า/data
เข้ารหัสด้วยหรือไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสเมื่อบู๊ตครั้งแรก จึงไม่ควรตั้งรหัสผ่าน ดังนั้นเราจึงถอดรหัสและติดตั้ง/data
- เมานต์
/data
จากนั้น
init
จะเมานต์/data
บน tmpfs RAMDisk โดยใช้พารามิเตอร์ที่รับมาจากro.crypto.tmpfs_options
ซึ่งตั้งค่าไว้ในinit.rc
- เริ่มกรอบ
vold
ตั้งค่าvold.decrypt
เป็นtrigger_restart_framework
ซึ่งจะดำเนินต่อตามกระบวนการบูตตามปกติ
เข้ารหัสอุปกรณ์ที่มีอยู่
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณเข้ารหัส Android K หรืออุปกรณ์รุ่นก่อนหน้าที่ไม่ได้เข้ารหัสซึ่งถูกย้ายไปยัง L
กระบวนการนี้เริ่มต้นโดยผู้ใช้และเรียกว่า "inplace encryption" ในรหัส เมื่อผู้ใช้เลือกที่จะเข้ารหัสอุปกรณ์ UI จะตรวจสอบให้แน่ใจว่าแบตเตอรี่ชาร์จเต็มแล้วและเสียบอะแดปเตอร์ AC เพื่อให้มีพลังงานเพียงพอที่จะเสร็จสิ้นกระบวนการเข้ารหัส
คำเตือน: หากอุปกรณ์ไฟฟ้าหมดและปิดก่อนที่จะเข้ารหัสเสร็จ ข้อมูลไฟล์จะอยู่ในสถานะเข้ารหัสบางส่วน ต้องรีเซ็ตอุปกรณ์เป็นค่าเริ่มต้นและข้อมูลทั้งหมดจะสูญหาย
ในการเปิดใช้งานการเข้ารหัสแบบ vold
จะเริ่มวนรอบเพื่ออ่านแต่ละส่วนของอุปกรณ์บล็อกจริง จากนั้นจึงเขียนไปยังอุปกรณ์บล็อกการเข้ารหัสลับ vold
ตรวจสอบเพื่อดูว่ามีการใช้เซกเตอร์หรือไม่ก่อนที่จะอ่านและเขียน ซึ่งทำให้การเข้ารหัสเร็วขึ้นมากบนอุปกรณ์ใหม่ที่มีข้อมูลเพียงเล็กน้อยหรือไม่มีเลย
สถานะของอุปกรณ์ : ตั้งค่า ro.crypto.state = "unencrypted"
และเรียกใช้ทริกเกอร์ init
ที่ไม่ได้ on nonencrypted
เพื่อดำเนินการบูทต่อไป
- ตรวจสอบรหัสผ่าน
UI เรียก
vold
ด้วยคำสั่งcryptfs enablecrypto inplace
โดยที่passwd
เป็นรหัสผ่านล็อคหน้าจอของผู้ใช้ - ถอดกรอบ
vold
ตรวจสอบข้อผิดพลาด ส่งกลับ -1 หากไม่สามารถเข้ารหัส และพิมพ์เหตุผลในบันทึก หากสามารถเข้ารหัสได้ จะตั้งค่าคุณสมบัติvold.decrypt
เป็นtrigger_shutdown_framework
สิ่งนี้ทำให้init.rc
หยุดบริการในคลาสlate_start
และmain
- สร้างส่วนท้ายของการเข้ารหัสลับ
- สร้างไฟล์เบรดครัมบ์
- รีบูต
- ตรวจหาไฟล์เบรดครัมบ์
- เริ่มการเข้ารหัส
/data
จากนั้น
vold
จะตั้งค่าการแมป crypto ซึ่งสร้างอุปกรณ์บล็อก crypto เสมือนจริงที่แมปบนอุปกรณ์บล็อกจริง แต่เข้ารหัสแต่ละเซกเตอร์ตามที่เขียน และถอดรหัสแต่ละเซกเตอร์ตามที่อ่าน จากนั้นvold
จะสร้างและเขียนข้อมูลเมตาของการเข้ารหัสลับ - ขณะที่กำลังเข้ารหัส ให้เมานต์ tmpfs
vold
ติดตั้ง tmpfs/data
(โดยใช้ตัวเลือก tmpfs จากro.crypto.tmpfs_options
) และตั้งค่าคุณสมบัติvold.encrypt_progress
เป็น 0vold
เตรียม tmpfs/data
สำหรับการบูตระบบที่เข้ารหัส และตั้งค่าคุณสมบัติvold.decrypt
เป็น:trigger_restart_min_framework
- นำกรอบการแสดงความคืบหน้า
trigger_restart_min_framework
ทำให้init.rc
เริ่มบริการระดับmain
เมื่อเฟรมเวิร์กเห็นว่าvold.encrypt_progress
ตั้งค่าเป็น 0 จะแสดง UI ของแถบความคืบหน้า ซึ่งจะสอบถามคุณสมบัตินั้นทุก ๆ ห้าวินาทีและอัปเดตแถบความคืบหน้า ลูปการเข้ารหัสจะอัปเดตvold.encrypt_progress
ทุกครั้งที่เข้ารหัสพาร์ติชันอีกเปอร์เซ็นต์ - เมื่อ
/data
ถูกเข้ารหัส ให้อัปเดตส่วนท้ายของ cryptoเมื่อเข้ารหัส
/data
สำเร็จvold
จะล้างแฟล็กENCRYPTION_IN_PROGRESS
ในข้อมูลเมตาเมื่อปลดล็อคอุปกรณ์สำเร็จ รหัสผ่านจะถูกใช้เพื่อเข้ารหัสมาสเตอร์คีย์และส่วนท้ายของการเข้ารหัสจะได้รับการอัปเดต
หากการรีบูตล้มเหลวด้วยเหตุผลบางประการ
vold
จะตั้งค่าคุณสมบัติvold.encrypt_progress
เป็นerror_reboot_failed
และ UI ควรแสดงข้อความที่ขอให้ผู้ใช้กดปุ่มเพื่อรีบูต สิ่งนี้ไม่คาดว่าจะเกิดขึ้น
การเริ่มต้นอุปกรณ์ที่เข้ารหัสด้วยการเข้ารหัสเริ่มต้น
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณบู๊ตอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสเมื่อบู๊ตครั้งแรก จึงไม่ควรตั้งรหัสผ่าน ดังนั้นจึงเป็นสถานะ การเข้ารหัสเริ่มต้น
- ตรวจหาการเข้ารหัส
/data
โดยไม่มีรหัสผ่านตรวจหาว่าอุปกรณ์ Android ได้รับการเข้ารหัสเนื่องจาก
/data
ไม่สามารถเมานต์ได้ และมีการตั้งค่าแฟล็กที่encryptable
หรือบังคับforceencrypt
อย่างใดอย่างหนึ่งvold
ตั้งค่าvold.decrypt
เป็นtrigger_default_encryption
ซึ่งเริ่มบริการdefaultcrypto
trigger_default_encryption
ตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า/data
ถูกเข้ารหัสด้วยหรือไม่มีรหัสผ่าน - ถอดรหัส/ข้อมูล
สร้างอุปกรณ์
dm-crypt
เหนืออุปกรณ์บล็อกเพื่อให้อุปกรณ์พร้อมใช้งาน - เมานต์ / ข้อมูล
จากนั้น
vold
จะเมานต์พาร์ติชันจริง/data
ถอดรหัสแล้ว จากนั้นเตรียมพาร์ติชันใหม่ มันตั้งค่าคุณสมบัติvold.post_fs_data_done
เป็น 0 แล้วตั้งค่าvold.decrypt
เป็นtrigger_post_fs_data
สิ่งนี้ทำให้init.rc
เรียกใช้คำสั่งpost-fs-data
พวกเขาจะสร้างไดเร็กทอรีหรือลิงก์ที่จำเป็น จากนั้นตั้งค่าvold.post_fs_data_done
เป็น 1เมื่อ
vold
เห็น 1 ในคุณสมบัตินั้น มันจะตั้งค่าคุณสมบัติvold.decrypt
เป็น:trigger_restart_framework.
สิ่งนี้ทำให้init.rc
เริ่มบริการในคลาสmain
อีกครั้งและเริ่มบริการในคลาสlate_start
เป็นครั้งแรกตั้งแต่บูต - เริ่มกรอบ
ตอนนี้เฟรมเวิร์กบูตบริการทั้งหมดโดยใช้การถอดรหัส
/data
และระบบพร้อมใช้งานแล้ว
การเริ่มต้นอุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณบู๊ตอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้ รหัสผ่านของอุปกรณ์อาจเป็นพิน รูปแบบ หรือรหัสผ่านก็ได้
- ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
ตรวจพบว่าอุปกรณ์ Android ได้รับการเข้ารหัสเนื่องจากการตั้งค่าสถานะ
ro.crypto.state = "encrypted"
vold
ตั้งค่าvold.decrypt
เป็นtrigger_restart_min_framework
เนื่องจาก/data
ถูกเข้ารหัสด้วยรหัสผ่าน - เมานต์ tmpfs
init
ตั้งค่าห้าคุณสมบัติเพื่อบันทึกตัวเลือกการเมาต์เริ่มต้นที่กำหนดสำหรับ/data
พร้อมพารามิเตอร์ที่ส่งผ่านจากinit.rc
vold
ใช้คุณสมบัติเหล่านี้เพื่อตั้งค่าการแมป crypto:-
ro.crypto.fs_type
-
ro.crypto.fs_real_blkdev
-
ro.crypto.fs_mnt_point
-
ro.crypto.fs_options
-
ro.crypto.fs_flags
(เลขฐานสิบหก ASCII 8 หลักนำหน้าด้วย 0x)
-
- เริ่มกรอบการทำงานเพื่อขอรหัสผ่าน
กรอบงานเริ่มต้นขึ้นและเห็นว่ามีการตั้งค่า
vold.decrypt
เป็นtrigger_restart_min_framework
สิ่งนี้บอกเฟรมเวิร์กว่ากำลังบูทบนดิสก์ tmpfs/data
และจำเป็นต้องได้รับรหัสผ่านผู้ใช้อย่างไรก็ตาม ก่อนอื่นต้องแน่ใจว่าดิสก์ได้รับการเข้ารหัสอย่างถูกต้อง มันส่งคำสั่ง
cryptfs cryptocomplete
ไปยังvold
vold
คืนค่า 0 หากการเข้ารหัสเสร็จสมบูรณ์, -1 สำหรับข้อผิดพลาดภายใน หรือ -2 หากการเข้ารหัสไม่เสร็จสมบูรณ์vold
กำหนดสิ่งนี้โดยดูในข้อมูลเมตาของ crypto สำหรับแฟCRYPTO_ENCRYPTION_IN_PROGRESS
หากตั้งค่าไว้ แสดงว่ากระบวนการเข้ารหัสถูกขัดจังหวะ และไม่มีข้อมูลที่ใช้งานได้บนอุปกรณ์ หากvold
ส่งกลับข้อผิดพลาด UI ควรแสดงข้อความให้ผู้ใช้รีบูตและรีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น และให้ผู้ใช้กดปุ่มเพื่อดำเนินการดังกล่าว - ถอดรหัสข้อมูลด้วยรหัสผ่าน
เมื่อ
cryptfs cryptocomplete
สำเร็จ เฟรมเวิร์กจะแสดง UI ที่ขอรหัสผ่านของดิสก์ UI ตรวจสอบรหัสผ่านโดยส่งคำสั่งcryptfs checkpw
ไปยังvold
หากรหัสผ่านถูกต้อง (ซึ่งกำหนดโดยการติดตั้ง/data
ที่ถอดรหัสเรียบร้อยแล้วที่ตำแหน่งชั่วคราว จากนั้นยกเลิกการต่อเชื่อม)vold
จะบันทึกชื่อของอุปกรณ์บล็อกถอดรหัสในคุณสมบัติro.crypto.fs_crypto_blkdev
และส่งกลับสถานะ 0 ไปยัง UI . หากรหัสผ่านไม่ถูกต้อง จะส่งกลับ -1 ไปที่ UI - หยุดกรอบ
UI สร้างกราฟิกสำหรับบูต crypto จากนั้นเรียก
vold
ด้วยคำสั่งcryptfs restart
vold
ตั้งค่าคุณสมบัติvold.decrypt
เป็นtrigger_reset_main
ซึ่งทำให้init.rc
ทำclass_reset main
สิ่งนี้จะหยุดบริการทั้งหมดในคลาสหลัก ซึ่งอนุญาตให้ยกเลิกการต่อเชื่อม tmpfs/data
- เมานต์
/data
จากนั้น
vold
จะเมานต์พาร์ติชัน/data
จริงที่ถอดรหัสแล้วและเตรียมพาร์ติชันใหม่ (ซึ่งอาจไม่เคยเตรียมมาก่อนหากถูกเข้ารหัสด้วยตัวเลือกการลบ ซึ่งไม่รองรับในรุ่นแรก) มันตั้งค่าคุณสมบัติvold.post_fs_data_done
เป็น 0 แล้วตั้งค่าvold.decrypt
เป็นtrigger_post_fs_data
สิ่งนี้ทำให้init.rc
เรียกใช้คำสั่งpost-fs-data
พวกเขาจะสร้างไดเร็กทอรีหรือลิงก์ที่จำเป็น จากนั้นตั้งค่าvold.post_fs_data_done
เป็น 1 เมื่อvold
เห็น 1 ในคุณสมบัตินั้น ก็จะตั้งค่าคุณสมบัติvold.decrypt
เป็นtrigger_restart_framework
สิ่งนี้ทำให้init.rc
เริ่มบริการในคลาสmain
อีกครั้งและเริ่มบริการในคลาสlate_start
เป็นครั้งแรกตั้งแต่บูต - เริ่มเฟรมเวิร์กแบบเต็ม
ตอนนี้เฟรมเวิร์กบูตบริการทั้งหมดโดยใช้ระบบไฟล์
/data
ที่ถอดรหัส และระบบพร้อมใช้งานแล้ว
ความล้มเหลว
อุปกรณ์ที่ถอดรหัสไม่สำเร็จอาจทำงานผิดปกติด้วยเหตุผลบางประการ อุปกรณ์เริ่มต้นด้วยชุดขั้นตอนปกติในการบู๊ต:
- ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
- เมานต์ tmpfs
- เริ่มกรอบการทำงานเพื่อขอรหัสผ่าน
แต่หลังจากเฟรมเวิร์กเปิดขึ้น อุปกรณ์อาจพบข้อผิดพลาดบางอย่าง:
- รหัสผ่านตรงกันแต่ไม่สามารถถอดรหัสข้อมูลได้
- ผู้ใช้ป้อนรหัสผ่านผิด 30 ครั้ง
หากไม่สามารถแก้ไขข้อผิดพลาดเหล่านี้ได้ ให้แจ้งผู้ใช้ให้ล้างข้อมูลจากโรงงาน :
หาก vold
ตรวจพบข้อผิดพลาดระหว่างกระบวนการเข้ารหัส และถ้ายังไม่มีการทำลายข้อมูลและเฟรมเวิร์กไม่ทำงาน vold
จะตั้งค่าคุณสมบัติ vold.encrypt_progress
เป็น error_not_encrypted
UI จะแจ้งให้ผู้ใช้รีบูตและแจ้งเตือนว่ากระบวนการเข้ารหัสไม่เคยเริ่มต้นขึ้น หากข้อผิดพลาดเกิดขึ้นหลังจากที่เฟรมเวิร์กถูกยกเลิก แต่ก่อนที่แถบความคืบหน้า UI จะขึ้น vold
จะรีบูตระบบ หากการรีบูตล้มเหลว จะตั้งค่า vold.encrypt_progress
เป็น error_shutting_down
และคืนค่า -1 แต่จะไม่มีอะไรให้จับผิด สิ่งนี้ไม่คาดว่าจะเกิดขึ้น
หาก vold
ตรวจพบข้อผิดพลาดระหว่างขั้นตอนการเข้ารหัส จะตั้งค่า vold.encrypt_progress
เป็น error_partially_encrypted
และคืนค่า -1 จากนั้น UI ควรแสดงข้อความแจ้งว่าการเข้ารหัสล้มเหลว และจัดเตรียมปุ่มให้ผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น
การจัดเก็บคีย์ที่เข้ารหัส
คีย์ที่เข้ารหัสจะถูกจัดเก็บไว้ในข้อมูลเมตาของการเข้ารหัสลับ การสำรองฮาร์ดแวร์ถูกนำมาใช้โดยใช้ความสามารถในการลงนามของ Trusted Execution Environment (TEE) ก่อนหน้านี้ เราเข้ารหัสมาสเตอร์คีย์ด้วยคีย์ที่สร้างขึ้นโดยการใช้ scrypt กับรหัสผ่านของผู้ใช้และเกลือที่เก็บไว้ เพื่อทำให้คีย์สามารถต้านทานการโจมตีนอกกรอบได้ เราจึงขยายอัลกอริทึมนี้โดยการเซ็นชื่อคีย์ผลลัพธ์ด้วยคีย์ TEE ที่เก็บไว้ ลายเซ็นที่เป็นผลลัพธ์จะเปลี่ยนเป็นคีย์ความยาวที่เหมาะสมโดยการใช้ scrypt อีกหนึ่งโปรแกรม คีย์นี้ใช้เพื่อเข้ารหัสและถอดรหัสคีย์หลัก ในการจัดเก็บคีย์นี้:
- สร้างคีย์เข้ารหัสดิสก์ (DEK) แบบสุ่ม 16 ไบต์และเกลือ 16 ไบต์
- ใช้ scrypt กับรหัสผ่านผู้ใช้และเกลือเพื่อสร้างคีย์กลาง 32 ไบต์ 1 (IK1)
- Pad IK1 ที่มีศูนย์ไบต์เป็นขนาดของคีย์ส่วนตัวที่เชื่อมต่อกับฮาร์ดแวร์ (HBK) โดยเฉพาะอย่างยิ่ง เราใส่เป็น: 00 || IK1 || 00..00; หนึ่งศูนย์ไบต์, 32 IK1 ไบต์, 223 ศูนย์ไบต์
- ลงชื่อ IK1 ที่บุนวมด้วย HBK เพื่อสร้าง IK2 ขนาด 256 ไบต์
- ใช้ scrypt กับ IK2 และเกลือ (เกลือเดียวกับขั้นตอนที่ 2) เพื่อสร้าง IK3 ขนาด 32 ไบต์
- ใช้ 16 ไบต์แรกของ IK3 เป็น KEK และ 16 ไบต์สุดท้ายเป็น IV
- เข้ารหัส DEK ด้วย AES_CBC ด้วยคีย์ KEK และการเริ่มต้นเวกเตอร์ IV
การเปลี่ยนรหัสผ่าน
เมื่อผู้ใช้เลือกที่จะเปลี่ยนหรือลบรหัสผ่านในการตั้งค่า UI จะส่งคำสั่ง cryptfs changepw
ไปยัง vold
และ vold
จะเข้ารหัสดิสก์มาสเตอร์คีย์อีกครั้งด้วยรหัสผ่านใหม่
คุณสมบัติการเข้ารหัส
vold
และ init
สื่อสารกันโดยการตั้งค่าคุณสมบัติ นี่คือรายการของคุณสมบัติที่มีสำหรับการเข้ารหัส
คุณสมบัติของโวล
คุณสมบัติ | คำอธิบาย |
---|---|
vold.decrypt trigger_encryption | เข้ารหัสไดรฟ์โดยไม่มีรหัสผ่าน |
vold.decrypt trigger_default_encryption | ตรวจสอบไดรฟ์เพื่อดูว่ามีการเข้ารหัสโดยไม่มีรหัสผ่านหรือไม่ หากเป็นเช่นนั้น ให้ถอดรหัสและติดตั้ง มิฉะนั้นให้ตั้งค่า vold.decrypt เป็น trigger_restart_min_framework |
vold.decrypt trigger_reset_main | ตั้งค่าโดย vold เพื่อปิด UI ที่ขอรหัสผ่านดิสก์ |
vold.decrypt trigger_post_fs_data | ตั้งค่าโดย vold เพื่อเตรียม /data ด้วยไดเร็กทอรีที่จำเป็น และอื่นๆ |
vold.decrypt trigger_restart_framework | ตั้งค่าโดย vold เพื่อเริ่มเฟรมเวิร์กจริงและบริการทั้งหมด |
vold.decrypt trigger_shutdown_framework | ตั้งค่าโดย vold เพื่อปิดเฟรมเวิร์กทั้งหมดเพื่อเริ่มการเข้ารหัส |
vold.decrypt trigger_restart_min_framework | ตั้งค่าโดย vold เพื่อเริ่ม UI ของแถบความคืบหน้าสำหรับการเข้ารหัสหรือขอรหัสผ่าน ขึ้นอยู่กับค่าของ ro.crypto.state |
vold.encrypt_progress | เมื่อเฟรมเวิร์กเริ่มต้นขึ้น หากมีการตั้งค่าคุณสมบัตินี้ ให้เข้าสู่โหมด UI ของแถบความคืบหน้า |
vold.encrypt_progress 0 to 100 | UI ของแถบความคืบหน้าควรแสดงค่าเปอร์เซ็นต์ที่ตั้งไว้ |
vold.encrypt_progress error_partially_encrypted | UI ของแถบความคืบหน้าควรแสดงข้อความว่าการเข้ารหัสล้มเหลว และให้ผู้ใช้มีตัวเลือกในการรีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น |
vold.encrypt_progress error_reboot_failed | UI ของแถบความคืบหน้าควรแสดงข้อความแจ้งว่าการเข้ารหัสเสร็จสิ้น และให้ปุ่มแก่ผู้ใช้เพื่อรีบูตอุปกรณ์ ข้อผิดพลาดนี้ไม่คาดว่าจะเกิดขึ้น |
vold.encrypt_progress error_not_encrypted | UI ของแถบความคืบหน้าควรแสดงข้อความแจ้งว่ามีข้อผิดพลาดเกิดขึ้น ไม่มีข้อมูลใดถูกเข้ารหัสหรือสูญหาย และให้ปุ่มแก่ผู้ใช้เพื่อรีบูตระบบ |
vold.encrypt_progress error_shutting_down | UI ของแถบความคืบหน้าไม่ทำงาน ดังนั้นจึงไม่มีความชัดเจนว่าใครจะตอบสนองต่อข้อผิดพลาดนี้ และมันไม่ควรเกิดขึ้นอยู่ดี |
vold.post_fs_data_done 0 | กำหนดโดย vold ก่อนตั้งค่า vold.decrypt เป็น trigger_post_fs_data |
vold.post_fs_data_done 1 | ตั้งค่าโดย init.rc หรือ init.rc หลังจากเสร็จสิ้นภารกิจ post-fs-data |
คุณสมบัติเริ่มต้น
คุณสมบัติ | คำอธิบาย |
---|---|
ro.crypto.fs_crypto_blkdev | ตั้งค่าโดยคำสั่ง vold checkpw เพื่อใช้ในภายหลังโดยคำสั่ง vold restart |
ro.crypto.state unencrypted | ตั้งค่าโดย init เพื่อบอกว่าระบบนี้กำลังทำงานโดยไม่ได้เข้ารหัส /data ro.crypto.state encrypted ตั้งค่าโดย init เพื่อบอกว่าระบบนี้ทำงานด้วยการเข้ารหัส /data |
| คุณสมบัติทั้งห้านี้ถูกกำหนดโดย init เมื่อพยายามเมานต์ /data ด้วยพารามิเตอร์ที่ส่งผ่านจาก init.rc vold ใช้สิ่งเหล่านี้เพื่อตั้งค่าการแมป crypto |
ro.crypto.tmpfs_options | ตั้งค่าโดย init.rc พร้อมตัวเลือก init ควรใช้เมื่อติดตั้งระบบไฟล์ tmpfs /data |
เริ่มต้นการดำเนินการ
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption