การเข้ารหัสทั้งดิสก์คือกระบวนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดบนอุปกรณ์ Android โดยใช้คีย์ที่เข้ารหัส เมื่ออุปกรณ์ได้รับการเข้ารหัส ข้อมูลที่ผู้ใช้สร้างขึ้นทั้งหมดจะถูกเข้ารหัสโดยอัตโนมัติก่อนที่จะส่งไปยังดิสก์ และทั้งหมดจะอ่านถอดรหัสข้อมูลโดยอัตโนมัติก่อนที่จะกลับสู่กระบวนการเรียก
การเข้ารหัสทั้งดิสก์ถูกนำมาใช้กับ Android ใน 4.4 แต่ Android 5.0 นำเสนอคุณสมบัติใหม่เหล่านี้:
- สร้างการเข้ารหัสที่รวดเร็ว ซึ่งจะเข้ารหัสเฉพาะบล็อกที่ใช้บนพาร์ติชันข้อมูลเพื่อหลีกเลี่ยงการบูตครั้งแรกที่ใช้เวลานาน ปัจจุบันมีเพียงระบบไฟล์ ext4 และ f2fs เท่านั้นที่รองรับการเข้ารหัสที่รวดเร็ว
- เพิ่ม การตั้งค่าสถานะ fstab
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) ซึ่งใช้แฮชของลายเซ็นเพื่อเข้ารหัสคีย์หลัก
คุณสามารถค้นหารหัสผ่านเริ่มต้นที่กำหนดไว้ในไฟล์ Android Open Source Project cryptfs.cpp
เมื่อผู้ใช้ตั้งค่า PIN/รหัสผ่านหรือรหัสผ่านบนอุปกรณ์ จะมีการเข้ารหัสและจัดเก็บเฉพาะคีย์ 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
ตั้งค่าvold.decrypt
เป็นtrigger_restart_framework
ซึ่งดำเนินกระบวนการบู๊ตตามปกติต่อไป
เข้ารหัสอุปกรณ์ที่มีอยู่
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณเข้ารหัสอุปกรณ์ Android K หรือรุ่นก่อนหน้าที่ไม่ได้เข้ารหัสซึ่งย้ายไปยัง L
กระบวนการนี้เริ่มต้นโดยผู้ใช้และเรียกว่า "การเข้ารหัสแบบแทนที่" ในโค้ด เมื่อผู้ใช้เลือกที่จะเข้ารหัสอุปกรณ์ 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
จะสร้างและเขียนข้อมูลเมตาของ 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
ถูกเข้ารหัส ให้อัพเดตส่วนท้ายของ 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
บนอุปกรณ์บล็อกเพื่อให้อุปกรณ์พร้อมใช้งาน - เมานต์ /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
และระบบก็พร้อมใช้งาน
การเริ่มอุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณบูทอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้ รหัสผ่านของอุปกรณ์อาจเป็นพิน รูปแบบ หรือรหัสผ่านก็ได้
- ตรวจจับอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
ตรวจพบว่าอุปกรณ์ 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 ควรแสดงข้อความแจ้งว่าการเข้ารหัสล้มเหลว และให้ปุ่มให้ผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น
การจัดเก็บคีย์ที่เข้ารหัส
คีย์ที่เข้ารหัสจะถูกจัดเก็บไว้ในข้อมูลเมตาของ crypto การสนับสนุนฮาร์ดแวร์ถูกนำมาใช้โดยใช้ความสามารถในการลงนามของ Trusted Execution Environment (TEE) ก่อนหน้านี้ เราได้เข้ารหัสคีย์หลักด้วยคีย์ที่สร้างขึ้นโดยใช้การเข้ารหัสกับรหัสผ่านของผู้ใช้และเกลือที่เก็บไว้ เพื่อให้คีย์มีความยืดหยุ่นต่อการโจมตีนอกกรอบ เราได้ขยายอัลกอริธึมนี้โดยการเซ็นชื่อคีย์ผลลัพธ์ด้วยคีย์ TEE ที่เก็บไว้ จากนั้นลายเซ็นที่เป็นผลลัพธ์จะถูกเปลี่ยนเป็นคีย์ความยาวที่เหมาะสมโดยการใช้สคริปต์อีกครั้งหนึ่ง จากนั้นคีย์นี้จะใช้ในการเข้ารหัสและถอดรหัสคีย์หลัก หากต้องการจัดเก็บคีย์นี้:
- สร้างคีย์เข้ารหัสดิสก์ (DEK) แบบสุ่ม 16 ไบต์และเกลือ 16 ไบต์
- ใช้การเข้ารหัสกับรหัสผ่านผู้ใช้และเกลือเพื่อสร้างคีย์กลางขนาด 32 ไบต์ 1 (IK1)
- Pad IK1 ที่มีขนาดเป็นศูนย์ไบต์เท่ากับขนาดของคีย์ส่วนตัวที่ผูกกับฮาร์ดแวร์ (HBK) โดยเฉพาะเราแพดเป็น: 00 || IK1 || 00..00; หนึ่งไบต์เป็นศูนย์, 32 IK1 ไบต์, 223 ไบต์เป็นศูนย์
- ลงนามเบาะ IK1 ด้วย HBK เพื่อสร้าง IK2 ขนาด 256 ไบต์
- ใช้สคริปต์กับ 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