การเข้ารหัสทั้งดิสก์คือขั้นตอนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดในอุปกรณ์ Android โดยใช้คีย์ที่เข้ารหัส เมื่อระบบเข้ารหัสอุปกรณ์แล้ว ข้อมูลทั้งหมดที่ผู้ใช้สร้างขึ้นจะได้รับการเข้ารหัสโดยอัตโนมัติก่อนส่งไปที่ดิสก์ และการอ่านทั้งหมดจะถอดรหัสข้อมูลโดยอัตโนมัติก่อนส่งไปยังกระบวนการเรียกใช้
การเข้ารหัสทั้งดิสก์เปิดตัวกับ Android ในรุ่น 4.4 แต่ Android 5.0 เปิดตัวฟีเจอร์ใหม่ต่อไปนี้
- สร้างการเข้ารหัสที่รวดเร็ว ซึ่งจะเข้ารหัสเฉพาะบล็อกที่ใช้ในพาร์ติชันข้อมูลเพื่อหลีกเลี่ยงการบูตครั้งแรกที่ใช้เวลานาน ปัจจุบันมีเพียงระบบไฟล์ ext4 และ f2fs เท่านั้นที่รองรับการเข้ารหัสอย่างรวดเร็ว
- เพิ่ม
forceencrypt
Flag fstab เพื่อเข้ารหัสในการบูตครั้งแรก - เพิ่มการรองรับรูปแบบและการเข้ารหัสโดยไม่ต้องใช้รหัสผ่าน
- เพิ่มพื้นที่เก็บข้อมูลที่สนับสนุนฮาร์ดแวร์ของคีย์การเข้ารหัสโดยใช้ความสามารถในการลงชื่อของสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) (เช่น ใน TrustZone) ดูรายละเอียดเพิ่มเติมได้ที่การจัดเก็บคีย์ที่เข้ารหัส
ข้อควรระวัง: อุปกรณ์ที่อัปเกรดเป็น Android 5.0 แล้วมีการเข้ารหัสอาจเปลี่ยนกลับเป็นสถานะไม่เข้ารหัสได้ด้วยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น อุปกรณ์ Android 5.0 ใหม่ที่เข้ารหัสเมื่อเปิดเครื่องครั้งแรกจะกลับไปเป็นสถานะที่ไม่เข้ารหัสไม่ได้
วิธีการทํางานของการเข้ารหัสดิสก์เต็มรูปแบบของ Android
การเข้ารหัสดิสก์ทั้งเครื่องของ Android อิงตาม dm-crypt
ซึ่งเป็นฟีเจอร์เคอร์เนลที่ทำงานในระดับอุปกรณ์บล็อก ด้วยเหตุนี้ การเข้ารหัสจึงใช้ได้กับ Embedded MultiMediaCard (eMMC) และอุปกรณ์แฟลชที่คล้ายกันซึ่งแสดงตัวตนต่อเคอร์เนลเป็นอุปกรณ์บล็อก YAFFS ไม่สามารถเข้ารหัสได้ เนื่องจากจะสื่อสารกับชิปแฟลช NAND โดยตรง
อัลกอริทึมการเข้ารหัสคือ 128 Advanced Encryption Standard (AES) ที่มีการทำเชนบล็อกการเข้ารหัส (CBC) และ ESSIV:SHA256 คีย์หลักได้รับการเข้ารหัสด้วย AES 128 บิตผ่านการเรียกใช้ไลบรารี OpenSSL คุณต้องใช้ 128 บิตขึ้นไปสำหรับคีย์ (โดยจะใช้ 256 บิตหรือไม่ก็ได้)
หมายเหตุ: OEM สามารถใช้ 128 บิตขึ้นไปเพื่อเข้ารหัสคีย์หลักได้
ในรุ่น Android 5.0 สถานะการเข้ารหัสมี 4 ประเภทดังนี้
- ค่าเริ่มต้น
- PIN
- รหัสผ่าน
- รูปแบบ
เมื่อบูตเครื่องครั้งแรก อุปกรณ์จะสร้างคีย์หลัก 128 บิตแบบสุ่ม แล้วแฮชคีย์นั้นด้วยรหัสผ่านเริ่มต้นและ Salt ที่เก็บไว้ รหัสผ่านเริ่มต้นคือ "default_password" อย่างไรก็ตาม แฮชที่ได้จะได้รับการรับรองผ่าน TEE (เช่น TrustZone) ด้วยเช่นกัน ซึ่งจะใช้แฮชของลายเซ็นเพื่อเข้ารหัสคีย์หลัก
คุณดูรหัสผ่านเริ่มต้นที่กำหนดไว้ในไฟล์ cryptfs.cpp ของโปรเจ็กต์โอเพนซอร์ส Android ได้
เมื่อผู้ใช้ตั้งค่า 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
ต้องไม่ได้รับการต่อเชื่อม อย่างไรก็ตาม หากต้องการแสดงอินเทอร์เฟซผู้ใช้ (UI) ใดๆ เฟรมเวิร์กจะต้องเริ่มต้นและเฟรมเวิร์กต้องใช้ /data
เพื่อทำงาน ระบบจะต่อเชื่อมระบบไฟล์ชั่วคราวใน /data
เพื่อแก้ปัญหานี้
ซึ่งจะช่วยให้ Android แสดงข้อความขอรหัสผ่าน แสดงความคืบหน้า หรือแนะนำให้ล้างข้อมูลได้ตามต้องการ ซึ่งตั้งข้อจำกัดไว้ว่าหากต้องการเปลี่ยนจากระบบไฟล์ชั่วคราวเป็นระบบไฟล์ /data
ที่แท้จริง ระบบจะต้องหยุดทุกกระบวนการที่มีไฟล์ที่เปิดอยู่ในระบบไฟล์ชั่วคราวและรีสตาร์ทกระบวนการเหล่านั้นในระบบไฟล์ /data
จริง ในการดำเนินการนี้ บริการทั้งหมดต้องอยู่ใน 1 จาก 3 กลุ่ม ได้แก่ core
, main
และ late_start
core
: ไม่ต้องปิดเครื่องหลังจากเปิดเครื่องmain
: ปิดเครื่องแล้วรีสตาร์ทหลังจากป้อนรหัสผ่านดิสก์แล้วlate_start
: ไม่เริ่มต้นจนกว่าจะมีการถอดรหัสและต่อเชื่อม/data
หากต้องการทริกเกอร์การดำเนินการเหล่านี้ ระบบจะตั้งค่าพร็อพเพอร์ตี้ vold.decrypt
เป็นสตริงต่างๆ
หากต้องการหยุดและเริ่มบริการใหม่ คำสั่ง init
มีดังนี้
class_reset
: หยุดบริการแต่อนุญาตให้เริ่มต้นใหม่ได้ด้วย class_startclass_start
: รีสตาร์ทบริการclass_stop
: หยุดบริการและเพิ่ม FlagSVC_DISABLED
บริการที่หยุดทำงานจะไม่ตอบสนองต่อclass_start
ขั้นตอน
อุปกรณ์ที่เข้ารหัสมีขั้นตอน 4 ขั้นตอน อุปกรณ์จะเข้ารหัสเพียงครั้งเดียว จากนั้นทำตามขั้นตอนการเปิดเครื่องปกติ
- วิธีเข้ารหัสอุปกรณ์ที่ไม่ได้เข้ารหัสก่อนหน้านี้
- เข้ารหัสอุปกรณ์ใหม่ด้วย
forceencrypt
: การเข้ารหัสแบบบังคับ เมื่อบูตครั้งแรก (เริ่มตั้งแต่ Android L) - เข้ารหัสอุปกรณ์ที่มีอยู่: การเข้ารหัสที่ผู้ใช้เริ่ม (Android K และเก่ากว่า)
- เข้ารหัสอุปกรณ์ใหม่ด้วย
- เปิดเครื่องอุปกรณ์ที่เข้ารหัส ดังนี้
- การเริ่มอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งไม่มีการตั้งรหัสผ่าน (เกี่ยวข้องกับอุปกรณ์ที่ใช้ Android 5.0 ขึ้นไป)
- การเริ่มอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้
นอกเหนือจากขั้นตอนเหล่านี้แล้ว อุปกรณ์อาจเข้ารหัส /data
ไม่ได้ด้วย
เราจะอธิบายขั้นตอนแต่ละขั้นอย่างละเอียดที่ด้านล่าง
เข้ารหัสอุปกรณ์ใหม่ด้วยบังคับใช้การเข้ารหัส
นี่เป็นการเปิดเครื่องครั้งแรกตามปกติสำหรับอุปกรณ์ Android 5.0
- ตรวจหาระบบไฟล์ที่ไม่ได้เข้ารหัสด้วย Flag
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
- Mount
/data
จากนั้น
init
จะต่อเชื่อม/data
ใน RAMDisk ของ tmpfs โดยใช้พารามิเตอร์ที่รับจากro.crypto.tmpfs_options
ซึ่งตั้งค่าไว้ในinit.rc
- เริ่มเฟรมเวิร์ก
vold
จะตั้งค่าvold.decrypt
เป็นtrigger_restart_framework
ซึ่งจะดำเนินขั้นตอนการเปิดเครื่องตามปกติต่อไป
เข้ารหัสอุปกรณ์ที่มีอยู่
การดำเนินการนี้จะมีผลเมื่อคุณเข้ารหัสอุปกรณ์ Android K หรือเก่ากว่าที่ไม่ได้เข้ารหัสซึ่งย้ายข้อมูลไปยัง L แล้ว
กระบวนการนี้เริ่มต้นโดยผู้ใช้ และในโค้ดจะเรียกว่า "การเข้ารหัสภายใน" เมื่อผู้ใช้เลือกที่จะเข้ารหัสอุปกรณ์ UI จะตรวจสอบว่าแบตเตอรี่ชาร์จเต็มแล้วและเสียบปลั๊กอะแดปเตอร์ AC เพื่อให้มีพลังงานเพียงพอสำหรับขั้นตอนการเข้ารหัสให้เสร็จสิ้น
คำเตือน: หากแบตเตอรี่ของอุปกรณ์หมดและปิดไปก่อนการเข้ารหัสเสร็จสิ้น ข้อมูลไฟล์จะยังคงอยู่ในสถานะที่เข้ารหัสบางส่วน อุปกรณ์ต้องรีเซ็ตเป็นค่าเริ่มต้นและข้อมูลทั้งหมดจะหายไป
หากต้องการเปิดใช้การเข้ารหัสแบบอินเทอร์แอ็กทีฟ vold
จะเริ่มวนซ้ำเพื่ออ่านแต่ละส่วนของอุปกรณ์บล็อกจริง จากนั้นเขียนลงในอุปกรณ์บล็อกคริปโต vold
จะตรวจสอบว่าเซกเตอร์มีการใช้งานอยู่หรือไม่ก่อนที่จะอ่านและเขียน ซึ่งทำให้การเข้ารหัสเร็วขึ้นมากในอุปกรณ์ใหม่ที่มีข้อมูลน้อยหรือไม่มีข้อมูล
สถานะของอุปกรณ์: ตั้งค่า ro.crypto.state = "unencrypted"
และเรียกใช้ทริกเกอร์ on nonencrypted
init
เพื่อบูตต่อ
- ตรวจสอบรหัสผ่าน
UI จะเรียก
vold
ด้วยคําสั่งcryptfs enablecrypto inplace
โดยที่passwd
คือรหัสผ่านหน้าจอล็อกของผู้ใช้ - ลบเฟรมเวิร์กออก
vold
จะตรวจสอบข้อผิดพลาด แสดงผล -1 หากเข้ารหัสไม่ได้ และพิมพ์เหตุผลในบันทึก หากเข้ารหัสได้ ระบบจะตั้งค่าพร็อพเพอร์ตี้vold.decrypt
เป็นtrigger_shutdown_framework
การดำเนินการนี้จะทำให้init.rc
หยุดบริการในชั้นเรียนlate_start
และmain
- สร้างส่วนท้ายเกี่ยวกับคริปโต
- สร้างไฟล์เบรดครัมบ์
- รีบูต
- ตรวจหาไฟล์เบรดครัมบ์
- เริ่มเข้ารหัส
/data
vold
จะตั้งค่าการแมปการเข้ารหัส ซึ่งจะสร้างอุปกรณ์บล็อกการเข้ารหัสเสมือนจริงที่แมปกับอุปกรณ์บล็อกจริง แต่เข้ารหัสแต่ละภาคขณะเขียน และถอดรหัสแต่ละภาคขณะอ่าน จากนั้น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 ของแถบความคืบหน้า ซึ่งจะค้นหาพร็อพเพอร์ตี้ทุกๆ 5 วินาทีและอัปเดตแถบความคืบหน้า ลูปการเข้ารหัสจะอัปเดตvold.encrypt_progress
ทุกครั้งที่เข้ารหัสอีกเปอร์เซ็นต์หนึ่งของพาร์ติชัน - เมื่อ
/data
ได้รับการเข้ารหัส ให้อัปเดตส่วนท้ายการเข้ารหัสเมื่อเข้ารหัส
/data
เรียบร้อยแล้วvold
จะล้างแฟล็กENCRYPTION_IN_PROGRESS
ในข้อมูลเมตาเมื่ออุปกรณ์ปลดล็อกสำเร็จแล้ว ระบบจะใช้รหัสผ่านเพื่อเข้ารหัสคีย์หลักและส่วนท้ายของคริปโตได้รับการอัปเดต
หากการรีบูตไม่สำเร็จด้วยเหตุผลบางประการ
vold
จะตั้งค่าพร็อพเพอร์ตี้vold.encrypt_progress
เป็นerror_reboot_failed
และ UI ควรแสดงข้อความที่ขอให้ผู้ใช้กดปุ่มเพื่อรีบูต ซึ่งไม่ควรเกิดขึ้น
เริ่มอุปกรณ์ที่เข้ารหัสด้วยการเข้ารหัสเริ่มต้น
เหตุการณ์นี้จะเกิดขึ้นเมื่อคุณบูตอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสเมื่อบูตเครื่องครั้งแรก จึงไม่ควรมีการตั้งรหัสผ่าน และนี่คือสถานะการเข้ารหัสเริ่มต้น
- ตรวจหา
/data
ที่เข้ารหัสโดยไม่มีรหัสผ่านตรวจพบว่าอุปกรณ์ Android มีการเข้ารหัสเนื่องจากติดตั้ง
/data
ไม่ได้และมีการตั้งค่า Flagencryptable
หรือforceencrypt
ไว้รายการใดรายการหนึ่งแล้วvold
ตั้งค่าvold.decrypt
เป็นtrigger_default_encryption
ซึ่งจะเริ่มต้นบริการdefaultcrypto
trigger_default_encryption
จะตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า/data
เข้ารหัสโดยมีหรือไม่มีรหัสผ่าน - Decrypt /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
เป็นครั้งแรกตั้งแต่เปิดเครื่องด้วย - Start Framework
ตอนนี้เฟรมเวิร์กจะบูตบริการทั้งหมดโดยใช้
/data
ที่ถอดรหัสแล้ว และระบบก็พร้อมใช้งาน
เริ่มใช้อุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น
สิ่งที่จะเกิดขึ้นเมื่อคุณบูตอุปกรณ์ที่เข้ารหัสซึ่งมีการตั้งรหัสผ่านไว้ รหัสผ่านของอุปกรณ์อาจเป็น PIN, รูปแบบ หรือรหัสผ่าน
- ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
ตรวจพบว่าอุปกรณ์ Android ได้รับการเข้ารหัสเนื่องจาก Flag
ro.crypto.state = "encrypted"
vold
ตั้งค่าvold.decrypt
เป็นtrigger_restart_min_framework
เนื่องจาก/data
เข้ารหัสด้วยรหัสผ่าน - ต่อเชื่อม tmpfs
init
กำหนดพร็อพเพอร์ตี้ 5 รายการเพื่อบันทึกตัวเลือกการต่อเชื่อมเริ่มต้นที่ใช้กับ/data
ซึ่งมีพารามิเตอร์ที่ส่งจากinit.rc
vold
ใช้พร็อพเพอร์ตี้เหล่านี้ในการตั้งค่าการแมปคริปโตro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(ตัวเลขฐาน 16 8 หลักของ ASCII ตามด้วย 0x)
- เริ่มเฟรมเวิร์กเพื่อแจ้งให้ป้อนรหัสผ่าน
เฟรมเวิร์กเริ่มต้นขึ้นและเห็นว่าตั้งค่า
vold.decrypt
เป็นtrigger_restart_min_framework
ซึ่งจะบอกเฟรมเวิร์กว่ากำลังบูตในดิสก์ tmpfs/data
และต้องได้รับรหัสผ่านของผู้ใช้อย่างไรก็ตาม อันดับแรกต้องตรวจสอบว่าดิสก์ได้รับการเข้ารหัสอย่างถูกต้อง ซึ่งจะส่งคำสั่ง
cryptfs cryptocomplete
ไปยังvold
vold
จะแสดงผลเป็น 0 หากการเข้ารหัสเสร็จสมบูรณ์ -1 หากมีข้อผิดพลาดภายใน หรือ -2 หากการเข้ารหัสไม่เสร็จสมบูรณ์vold
จะระบุข้อมูลนี้โดยดูที่ธง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
ได้ - Mount
/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
ระบบไฟล์ที่ถอดรหัสแล้ว และระบบก็พร้อมใช้งาน
ไม่สำเร็จ
อุปกรณ์ที่ถอดรหัสไม่สำเร็จอาจมีปัญหาอยู่ 2-3 อย่าง อุปกรณ์จะเริ่มด้วยขั้นตอนชุดปกติในการเปิดเครื่องดังนี้
- ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
- ต่อเชื่อม 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 ควรแสดงข้อความแจ้งว่าการเข้ารหัสล้มเหลว และมีปุ่มให้ผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น
จัดเก็บคีย์ที่เข้ารหัส
ระบบจะจัดเก็บคีย์ที่เข้ารหัสไว้ในข้อมูลเมตาการเข้ารหัส แบ็กกิ้งฮาร์ดแวร์จะติดตั้งใช้งานโดยใช้ความสามารถในการลงชื่อของสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) ก่อนหน้านี้ เราเข้ารหัสคีย์หลักด้วยคีย์ที่สร้างจากการใช้ Scrypt กับรหัสผ่านของผู้ใช้และ Salt ที่เก็บไว้ เราขยายอัลกอริทึมนี้โดยการเซ็นคีย์ผลลัพธ์ด้วยคีย์ TEE ที่จัดเก็บไว้ เพื่อให้คีย์มีความยืดหยุ่นจากการโจมตีนอกกรอบ จากนั้นระบบจะเปลี่ยนลายเซ็นที่ได้ให้เป็นคีย์ที่มีความยาวที่เหมาะสมโดยใช้ scrypt อีก 1 ครั้ง จากนั้นระบบจะใช้คีย์นี้เพื่อเข้ารหัสและถอดรหัสคีย์หลัก วิธีจัดเก็บคีย์นี้
- สร้างคีย์การเข้ารหัสดิสก์ 16 ไบต์แบบสุ่ม (DEK) และ Salt 16 ไบต์
- ใช้สคริปต์กับรหัสผ่านผู้ใช้และ Salt เพื่อสร้างคีย์กลางขนาด 32 ไบต์ 1 (IK1)
- แพด IK1 ที่มีขนาด 0 ไบต์ตามขนาดของคีย์ส่วนตัวที่ผูกกับฮาร์ดแวร์ (HBK) กล่าวอย่างเจาะจงคือ เรากำหนดเป็น 00 || IK1 || 00..00; 1 ไบต์, 32 IK1 ไบต์, 223 ศูนย์ไบต์
- เซ็นชื่อ IK1 ที่เพิ่มความหนาด้วย HBK เพื่อสร้าง IK2 ขนาด 256 ไบต์
- ใช้การเข้ารหัสกับ IK2 และ Salt (เกลือเดียวกับขั้นตอนที่ 2) เพื่อสร้าง IK3 ขนาด 32 ไบต์
- ใช้ 16 ไบต์แรกของ IK3 เป็น KEK และ 16 ไบต์สุดท้ายเป็น IV
- เข้ารหัส DEK ด้วย AES_CBC, คีย์ KEK และเวกเตอร์การเริ่มต้น IV
เปลี่ยนรหัสผ่าน
เมื่อผู้ใช้เลือกที่จะเปลี่ยนหรือนำรหัสผ่านออกในการตั้งค่า UI จะส่งคำสั่ง cryptfs changepw
ไปยัง vold
และ vold
เข้ารหัสคีย์มาสเตอร์คีย์อีกครั้งด้วยรหัสผ่านใหม่
พร็อพเพอร์ตี้การเข้ารหัส
vold
และ init
สื่อสารกันโดยการตั้งค่าพร็อพเพอร์ตี้ รายการพร็อพเพอร์ตี้ที่พร้อมใช้งานสำหรับการเข้ารหัสมีดังนี้
พร็อพเพอร์ตี้ Vold
พร็อพเพอร์ตี้ | คำอธิบาย |
---|---|
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 จะเป็นผู้ตั้งค่าพร็อพเพอร์ตี้ทั้ง 5 รายการนี้เมื่อพยายามต่อเชื่อม /data ด้วยพารามิเตอร์ที่ส่งมาจาก init.rc vold ใช้ข้อมูลเหล่านี้เพื่อตั้งค่าการแมปคริปโต |
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