การเข้ารหัสทั้งดิสก์คือกระบวนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดในอุปกรณ์ Android โดยใช้ คีย์ที่เข้ารหัส เมื่ออุปกรณ์ได้รับการเข้ารหัสแล้ว ระบบจะเข้ารหัสข้อมูลทั้งหมดที่ผู้ใช้สร้างขึ้นโดยอัตโนมัติก่อนที่จะบันทึกลงในดิสก์ และจะถอดรหัสข้อมูลทั้งหมดโดยอัตโนมัติก่อนที่จะส่งคืนไปยังกระบวนการเรียก
การเข้ารหัสทั้งดิสก์เปิดตัวใน Android 4.4 แต่ Android 5.0 ได้เปิดตัวฟีเจอร์ใหม่ต่อไปนี้
- สร้างการเข้ารหัสอย่างรวดเร็ว ซึ่งจะเข้ารหัสเฉพาะบล็อกที่ใช้ในพาร์ติชันข้อมูล เพื่อหลีกเลี่ยงการบูตครั้งแรกที่ใช้เวลานาน ปัจจุบันมีเพียงระบบไฟล์ ext4 และ f2fs เท่านั้น ที่รองรับการเข้ารหัสอย่างรวดเร็ว
- เพิ่ม
forceencrypt
แฟล็ก fstab เพื่อเข้ารหัสในการบูตครั้งแรก - เพิ่มการรองรับรูปแบบและการเข้ารหัสโดยไม่ต้องใช้รหัสผ่าน
- เพิ่มการจัดเก็บคีย์การเข้ารหัสที่ได้รับการสนับสนุนจากฮาร์ดแวร์โดยใช้ความสามารถในการลงนามของสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) (เช่น ใน TrustZone) ดูรายละเอียดเพิ่มเติมได้ที่การจัดเก็บคีย์ที่เข้ารหัส
ข้อควรระวัง: อุปกรณ์ที่อัปเกรดเป็น Android 5.0 แล้ว เข้ารหัสจะเปลี่ยนกลับไปเป็นสถานะที่ไม่ได้เข้ารหัสได้โดยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น อุปกรณ์ Android 5.0 เครื่องใหม่ที่เข้ารหัสเมื่อเปิดเครื่องครั้งแรกจะเปลี่ยนกลับไปเป็นสถานะที่ไม่ได้เข้ารหัสไม่ได้
การเข้ารหัสดิสก์เต็มรูปแบบของ Android ทำงานอย่างไร
การเข้ารหัสทั้งดิสก์ของ Android อิงตาม dm-crypt
ซึ่งเป็นฟีเจอร์ของเคอร์เนล
ที่ทำงานในเลเยอร์อุปกรณ์บล็อก ด้วยเหตุนี้ การเข้ารหัสจึงใช้ได้กับ Embedded MultiMediaCard (eMMC) และ
อุปกรณ์แฟลชที่คล้ายกันซึ่งแสดงตัวเองต่อเคอร์เนลเป็นอุปกรณ์บล็อก
YAFFS ไม่สามารถเข้ารหัสได้เนื่องจากสื่อสารกับชิปแฟลช NAND แบบดิบโดยตรง
อัลกอริทึมการเข้ารหัสคือมาตรฐานการเข้ารหัสขั้นสูง (AES) 128 บิตที่มี การเชื่อมโยงบล็อกการเข้ารหัส (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
calls 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
Flows
อุปกรณ์ที่เข้ารหัสมี 4 โฟลว์ อุปกรณ์จะได้รับการเข้ารหัสเพียงครั้งเดียว แล้วจึงทำตามขั้นตอนการบูตปกติ
- วิธีเข้ารหัสอุปกรณ์ที่ไม่ได้เข้ารหัสก่อนหน้านี้
- เข้ารหัสอุปกรณ์ใหม่ด้วย
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
โดยไม่มีรหัสผ่าน (ไม่ได้ตั้งค่าไว้เนื่องจากควรเป็นอุปกรณ์ใหม่) - Mount 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
(ซึ่งจะเริ่มขั้นตอนด้านล่างสำหรับการติดตั้ง userdata ที่เข้ารหัสเริ่มต้น)trigger_default_encryption
ตรวจสอบ ประเภทการเข้ารหัสเพื่อดูว่า/data
เข้ารหัสโดยมีหรือไม่มี รหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 จะได้รับการเข้ารหัสเมื่อบูตครั้งแรก จึงไม่ควรมีการตั้งรหัสผ่าน ดังนั้นเราจึงถอดรหัสและติดตั้ง/data
- ติดตั้ง
/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
- สร้างส่วนท้ายของอีเมลเกี่ยวกับคริปโต
- สร้างไฟล์ Breadcrumb
- รีบูต
- ตรวจหาไฟล์เบรดครัมบ์
- เริ่มเข้ารหัส
/data
vold
จากนั้นจะตั้งค่าการแมปคริปโต ซึ่งจะสร้างอุปกรณ์บล็อกคริปโตเสมือน ที่แมปกับอุปกรณ์บล็อกจริง แต่จะเข้ารหัสแต่ละเซกเตอร์เมื่อมีการเขียน และถอดรหัสแต่ละเซกเตอร์เมื่อมีการอ่าน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 แถบความคืบหน้า ซึ่งจะค้นหาพร็อพเพอร์ตี้นั้นทุกๆ 5 วินาทีและอัปเดตแถบความคืบหน้า ลูปการเข้ารหัสจะอัปเดตvold.encrypt_progress
ทุกครั้งที่เข้ารหัสพาร์ติชันอีก 1% - เมื่อ
/data
ได้รับการเข้ารหัส ให้อัปเดตส่วนท้ายของข้อความที่เข้ารหัสเมื่อเข้ารหัส
/data
สำเร็จแล้วvold
จะล้าง แฟล็กENCRYPTION_IN_PROGRESS
ในข้อมูลเมตาเมื่อปลดล็อกอุปกรณ์สำเร็จแล้ว ระบบจะใช้รหัสผ่านเพื่อ เข้ารหัสคีย์หลักและอัปเดตส่วนท้ายของ Crypto
หากรีบูตไม่สำเร็จด้วยเหตุผลบางประการ
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
จะตั้งค่าพร็อพเพอร์ตี้vold.decrypt
เป็นtrigger_restart_framework.
ซึ่งจะทำให้init.rc
เริ่มบริการในคลาสmain
อีกครั้ง และเริ่มบริการในคลาสlate_start
เป็นครั้งแรก นับตั้งแต่เปิดเครื่อง - เฟรมเวิร์กเริ่มต้น
ตอนนี้เฟรมเวิร์กจะบูตบริการทั้งหมดโดยใช้
/data
ที่ถอดรหัสแล้ว และระบบพร้อมใช้งาน
เริ่มอุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น
สิ่งที่จะเกิดขึ้นเมื่อคุณบูตอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้ รหัสผ่านของอุปกรณ์อาจเป็น PIN, รูปแบบ หรือรหัสผ่าน
- ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
ตรวจพบว่าอุปกรณ์ Android ได้รับการเข้ารหัสเนื่องจากแฟล็ก
ro.crypto.state = "encrypted"
vold
ตั้งค่าvold.decrypt
เป็นtrigger_restart_min_framework
เนื่องจาก/data
เข้ารหัสด้วยรหัสผ่าน - Mount 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
(เลขฐานสิบหก 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
ได้ - ติดตั้ง
/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 ควรแสดงข้อความว่าการเข้ารหัส
ล้มเหลว และแสดงปุ่มให้ผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น
จัดเก็บคีย์ที่เข้ารหัส
ระบบจะจัดเก็บคีย์ที่เข้ารหัสไว้ในข้อมูลเมตาการเข้ารหัส การสนับสนุนฮาร์ดแวร์ จะดำเนินการโดยใช้ความสามารถในการลงนามของสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) ก่อนหน้านี้เราเข้ารหัสคีย์หลักด้วยคีย์ที่สร้างขึ้นโดยใช้ Scrypt กับรหัสผ่านของผู้ใช้และ Salt ที่จัดเก็บไว้ เราขยายอัลกอริทึมนี้ด้วยการลงนามคีย์ผลลัพธ์ ด้วยคีย์ TEE ที่จัดเก็บไว้ เพื่อให้คีย์มีความยืดหยุ่น ต่อการโจมตีภายนอก จากนั้นระบบจะเปลี่ยนลายเซ็นที่ได้ให้เป็นคีย์ที่มีความยาวเหมาะสม โดยใช้ scrypt อีกครั้ง จากนั้นจะใช้คีย์นี้เพื่อเข้ารหัส และถอดรหัสคีย์หลัก วิธีจัดเก็บคีย์นี้
- สร้างคีย์การเข้ารหัสดิสก์ (DEK) ขนาด 16 ไบต์และ Salt ขนาด 16 ไบต์แบบสุ่ม
- ใช้ scrypt กับรหัสผ่านของผู้ใช้และ Salt เพื่อสร้างคีย์กลาง 1 (IK1) ขนาด 32 ไบต์
- เพิ่มไบต์ศูนย์ลงใน IK1 ให้มีขนาดเท่ากับคีย์ส่วนตัวที่เชื่อมโยงกับฮาร์ดแวร์ (HBK) โดยเฉพาะอย่างยิ่ง เราจะเพิ่มแพดดิ้งเป็น 00 || IK1 || 00..00 ซึ่งประกอบด้วยไบต์ 0 หนึ่งไบต์, ไบต์ IK1 จำนวน 32 ไบต์ และไบต์ 0 จำนวน 223 ไบต์
- ลงนาม IK1 ที่มีการเพิ่มแพดดิ้งด้วย HBK เพื่อสร้าง IK2 ขนาด 256 ไบต์
- ใช้ scrypt กับ IK2 และ Salt (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 ที่ไม่ได้เข้ารหัส
/data ro.crypto.state encrypted ตั้งค่าโดย init เพื่อระบุว่า
ระบบนี้ทำงานด้วย /data ที่เข้ารหัส |
|
พร็อพเพอร์ตี้ทั้ง 5 รายการนี้จะตั้งค่าโดย
init เมื่อพยายามติดตั้ง /data ด้วยพารามิเตอร์ที่ส่งมาจาก
init.rc vold ใช้ข้อมูลเหล่านี้เพื่อตั้งค่าการแมปคริปโต |
ro.crypto.tmpfs_options |
ตั้งค่าโดย init.rc พร้อมตัวเลือกที่ init ควรใช้เมื่อ
ติดตั้งระบบไฟล์ tmpfs /data |
การดำเนินการ init
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