การเข้ารหัสทั้งดิสก์คือกระบวนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดบนอุปกรณ์ Android โดยใช้คีย์ที่เข้ารหัส เมื่ออุปกรณ์ได้รับการเข้ารหัสแล้ว ข้อมูลที่สร้างโดยผู้ใช้ทั้งหมดจะได้รับการเข้ารหัสโดยอัตโนมัติก่อนที่จะส่งไปยังดิสก์ และการอ่านทั้งหมดจะถอดรหัสข้อมูลโดยอัตโนมัติก่อนที่จะส่งกลับไปยังกระบวนการเรียก
การเข้ารหัสแบบเต็มดิสก์ได้รับการแนะนำให้รู้จักกับ Android ใน 4.4 แต่ Android 5.0 ได้แนะนำคุณสมบัติใหม่เหล่านี้:
- สร้างการเข้ารหัสที่รวดเร็ว ซึ่งเข้ารหัสเฉพาะบล็อกที่ใช้บนพาร์ติชั่นข้อมูลเพื่อหลีกเลี่ยงการบู๊ตครั้งแรกที่ใช้เวลานาน ขณะนี้มีเพียงระบบไฟล์ ext4 และ f2fs เท่านั้นที่รองรับการเข้ารหัสที่รวดเร็ว
- เพิ่ม
forceencrypt
fstab เพื่อเข้ารหัสในการบูตครั้งแรก - เพิ่มการรองรับรูปแบบและการเข้ารหัสโดยไม่ต้องใช้รหัสผ่าน
- เพิ่มที่เก็บข้อมูลฮาร์ดแวร์สำรองของคีย์การเข้ารหัสโดยใช้ความสามารถในการลงนามของ 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/pass หรือรหัสผ่านบนอุปกรณ์ เฉพาะคีย์ 128 บิตเท่านั้นที่จะได้รับการเข้ารหัสและจัดเก็บอีกครั้ง (เช่น การเปลี่ยนแปลง PIN/รหัสผ่าน/รูปแบบของผู้ใช้จะไม่ทำให้เกิดการเข้ารหัสข้อมูลผู้ใช้ซ้ำ) โปรดทราบว่า อุปกรณ์ที่ได้รับการจัดการ อาจอยู่ภายใต้ข้อจำกัดของ PIN, รูปแบบ หรือรหัสผ่าน
การเข้ารหัสได้รับการจัดการโดย init
และ vold
init
เรียก vold
และ vold ตั้งค่าคุณสมบัติเพื่อทริกเกอร์เหตุการณ์ใน init ส่วนอื่นๆ ของระบบยังพิจารณาคุณสมบัติเพื่อดำเนินการต่างๆ เช่น สถานะรายงาน ขอรหัสผ่าน หรือการแจ้งให้รีเซ็ตเป็นค่าจากโรงงานในกรณีที่เกิดข้อผิดพลาดร้ายแรง ในการเรียกใช้คุณลักษณะการเข้ารหัสใน vold
ระบบจะใช้คำสั่ง cryptfs
ของเครื่องมือบรรทัดคำสั่ง vdc
: checkpw
, restart
, enablecrypto
, changepw
, cryptocomplete
, verifypw
, setfield
, getfield
, mountdefaultencrypted
, getpwtype
, getpw
และ clearpw
ในการเข้ารหัส ถอดรหัสหรือล้าง /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
ไม่ได้ โฟลว์แต่ละอันมีรายละเอียดอธิบายไว้ด้านล่าง
เข้ารหัสอุปกรณ์ใหม่ด้วยforceencrypt
นี่เป็นการบู๊ตครั้งแรกตามปกติสำหรับอุปกรณ์ 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
เป็นtrigger_restart_framework
ซึ่งดำเนินการตามขั้นตอนการบู๊ตตามปกติ
เข้ารหัสอุปกรณ์ที่มีอยู่
นี่คือสิ่งที่จะเกิดขึ้นเมื่อคุณเข้ารหัส Android K ที่ไม่ได้เข้ารหัสหรืออุปกรณ์รุ่นก่อนหน้าซึ่งถูกย้ายไปยัง L
กระบวนการนี้เริ่มต้นโดยผู้ใช้และเรียกว่า "การเข้ารหัสแบบแทนที่" ในโค้ด เมื่อผู้ใช้เลือกเข้ารหัสอุปกรณ์ UI จะทำให้แน่ใจว่าแบตเตอรี่ชาร์จเต็มแล้ว และเสียบอะแดปเตอร์ AC อยู่ จึงมีพลังงานเพียงพอที่จะทำกระบวนการเข้ารหัสให้เสร็จสิ้น
คำเตือน: หากอุปกรณ์หมดพลังงานและปิดตัวลงก่อนที่จะเข้ารหัสเสร็จสิ้น ข้อมูลไฟล์จะถูกทิ้งให้อยู่ในสถานะเข้ารหัสบางส่วน อุปกรณ์จะต้องรีเซ็ตเป็นค่าเริ่มต้นจากโรงงานและข้อมูลทั้งหมดจะสูญหาย
ในการเปิดใช้งานการเข้ารหัสแบบ vold
จะเริ่มการวนซ้ำเพื่ออ่านแต่ละส่วนของอุปกรณ์บล็อกจริง จากนั้นเขียนลงในอุปกรณ์บล็อกการเข้ารหัส vold
ตรวจสอบเพื่อดูว่ามีการใช้งานเซกเตอร์ก่อนอ่านและเขียนหรือไม่ ซึ่งทำให้การเข้ารหัสเร็วขึ้นมากบนอุปกรณ์ใหม่ที่มีข้อมูลเพียงเล็กน้อยหรือไม่มีเลย
สถานะของอุปกรณ์ : ตั้งค่า ro.crypto.state = "unencrypted"
และเรียกใช้ on nonencrypted
init
trigger เพื่อทำการบูทต่อไป
- ตรวจสอบรหัสผ่าน
UI เรียกใช้
vold
ด้วยคำสั่งcryptfs enablecrypto inplace
โดยที่passwd
เป็นรหัสผ่านสำหรับล็อกหน้าจอของผู้ใช้ - ลงกรอบ
vold
ตรวจสอบข้อผิดพลาด ส่งกลับ -1 หากไม่สามารถเข้ารหัสได้ และพิมพ์เหตุผลในบันทึก หากสามารถเข้ารหัสได้ จะตั้งค่าคุณสมบัติvold.decrypt
เป็นtrigger_shutdown_framework
สิ่งนี้ทำให้init.rc
หยุดบริการในคลาสlate_start
และmain
- สร้างส่วนท้ายของการเข้ารหัสลับ
- สร้างไฟล์เบรดครัมบ์
- รีบูต
- ตรวจจับไฟล์เบรดครัมบ์
- เริ่มเข้ารหัส
/data
จากนั้น
vold
จะตั้งค่าการทำแผนที่ crypto ซึ่งสร้างอุปกรณ์บล็อก crypto เสมือนที่จับคู่กับอุปกรณ์บล็อกจริง แต่เข้ารหัสแต่ละส่วนตามที่เขียน และถอดรหัสแต่ละส่วนในขณะที่อ่านvold
จะสร้างและเขียนข้อมูลเมตาของ crypto - ขณะที่กำลังเข้ารหัส ให้เมานต์ 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
ถูกเข้ารหัส ให้อัปเดตส่วนท้ายของการเข้ารหัสลับเมื่อ
/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
ถูกเข้ารหัสโดยมีหรือไม่มีรหัสผ่านหรือไม่ - ถอดรหัส /data
สร้างอุปกรณ์
dm-crypt
เหนืออุปกรณ์บล็อกเพื่อให้อุปกรณ์พร้อมใช้งาน - เมานต์ /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
เป็นครั้งแรกตั้งแต่บูท - เริ่มเฟรมเวิร์ก
ตอนนี้เฟรมเวิร์กเริ่มบริการทั้งหมดโดยใช้ decrypted
/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 สร้างกราฟิกสำหรับบูตการเข้ารหัสแล้วเรียก
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) ก่อนหน้านี้ เราเข้ารหัสมาสเตอร์คีย์ด้วยคีย์ที่สร้างโดยการใช้การเข้ารหัสกับรหัสผ่านของผู้ใช้และเกลือที่เก็บไว้ เพื่อให้คีย์มีความยืดหยุ่นต่อการโจมตีแบบ off-box เราขยายอัลกอริทึมนี้โดยลงนามคีย์ผลลัพธ์ด้วยคีย์ TEE ที่เก็บไว้ ลายเซ็นผลลัพธ์จะกลายเป็นคีย์ความยาวที่เหมาะสมโดยแอปพลิเคชัน scrypt อีกหนึ่งโปรแกรม จากนั้นคีย์นี้จะใช้ในการเข้ารหัสและถอดรหัสมาสเตอร์คีย์ ในการจัดเก็บคีย์นี้:
- สร้างคีย์เข้ารหัสดิสก์ 16 ไบต์แบบสุ่ม (DEK) และเกลือ 16 ไบต์
- ใช้การเข้ารหัสกับรหัสผ่านผู้ใช้และเกลือเพื่อสร้างคีย์กลางขนาด 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 |
คุณสมบัติ init
คุณสมบัติ | คำอธิบาย |
---|---|
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