การเข้ารหัสทั้งดิสก์

การเข้ารหัสทั้งดิสก์คือขั้นตอนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดในอุปกรณ์ 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_start
  • class_start: รีสตาร์ทบริการ
  • class_stop: หยุดบริการและเพิ่ม Flag SVC_DISABLED บริการที่หยุดทำงานจะไม่ตอบสนองต่อ class_start

ขั้นตอน

อุปกรณ์ที่เข้ารหัสมีขั้นตอน 4 ขั้นตอน อุปกรณ์จะเข้ารหัสเพียงครั้งเดียว จากนั้นทำตามขั้นตอนการเปิดเครื่องปกติ

  • วิธีเข้ารหัสอุปกรณ์ที่ไม่ได้เข้ารหัสก่อนหน้านี้
    • เข้ารหัสอุปกรณ์ใหม่ด้วย forceencrypt: การเข้ารหัสแบบบังคับ เมื่อบูตครั้งแรก (เริ่มตั้งแต่ Android L)
    • เข้ารหัสอุปกรณ์ที่มีอยู่: การเข้ารหัสที่ผู้ใช้เริ่ม (Android K และเก่ากว่า)
  • เปิดเครื่องอุปกรณ์ที่เข้ารหัส ดังนี้
    • การเริ่มอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งไม่มีการตั้งรหัสผ่าน (เกี่ยวข้องกับอุปกรณ์ที่ใช้ Android 5.0 ขึ้นไป)
    • การเริ่มอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน: การบูตอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้

นอกเหนือจากขั้นตอนเหล่านี้แล้ว อุปกรณ์อาจเข้ารหัส /data ไม่ได้ด้วย เราจะอธิบายขั้นตอนแต่ละขั้นอย่างละเอียดที่ด้านล่าง

เข้ารหัสอุปกรณ์ใหม่ด้วยบังคับใช้การเข้ารหัส

นี่เป็นการเปิดเครื่องครั้งแรกตามปกติสำหรับอุปกรณ์ Android 5.0

  1. ตรวจหาระบบไฟล์ที่ไม่ได้เข้ารหัสด้วย Flag forceencrypt

    /data ไม่ได้เข้ารหัส แต่จำเป็นต้องเข้ารหัสเนื่องจาก forceencrypt กำหนดไว้ ยกเลิกการต่อเชื่อม /data

  2. เริ่มเข้ารหัส /data

    vold.decrypt = "trigger_encryption" จะทริกเกอร์ init.rc ซึ่งทำให้ vold เข้ารหัส /data โดยไม่ใช้รหัสผ่าน (ไม่ได้ตั้งค่าไว้เนื่องจากควรเป็นอุปกรณ์ใหม่)

  3. ต่อเชื่อม tmpfs

    vold ต่อเชื่อม tmpfs /data (โดยใช้ตัวเลือก tmpfs จาก ro.crypto.tmpfs_options) และตั้งค่าพร็อพเพอร์ตี้ vold.encrypt_progress เป็น 0 vold เตรียม tmpfs /data สำหรับการเปิดเครื่องระบบที่เข้ารหัสและตั้งค่าพร็อพเพอร์ตี้ vold.decrypt เป็น trigger_restart_min_framework

  4. แสดงเฟรมเวิร์กเพื่อแสดงความคืบหน้า

    เนื่องจากอุปกรณ์ไม่มีข้อมูลที่จะเข้ารหัส แถบความคืบหน้าจะไม่ปรากฏขึ้นบ่อยนักเนื่องจากการเข้ารหัสเกิดขึ้นเร็วมาก โปรดดูเข้ารหัสอุปกรณ์ที่มีอยู่สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ UI ความคืบหน้า

  5. เมื่อเข้ารหัส /data แล้ว ให้ลบเฟรมเวิร์กออก

    vold จะตั้งค่า vold.decrypt เป็น trigger_default_encryption ซึ่งเริ่มต้นบริการ defaultcrypto (ขั้นตอนนี้จะเริ่มขั้นตอนด้านล่างสำหรับการต่อเชื่อมข้อมูลผู้ใช้ที่เข้ารหัสเริ่มต้น) trigger_default_encryption ตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า /data ได้รับการเข้ารหัสโดยมีหรือไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสเมื่อเปิดเครื่องครั้งแรก จึงไม่ควรตั้งรหัสผ่าน เราจึงถอดรหัสและต่อเชื่อม /data

  6. Mount /data

    จากนั้น init จะต่อเชื่อม /data ใน RAMDisk ของ tmpfs โดยใช้พารามิเตอร์ที่รับจาก ro.crypto.tmpfs_options ซึ่งตั้งค่าไว้ใน init.rc

  7. เริ่มเฟรมเวิร์ก

    vold จะตั้งค่า vold.decrypt เป็น trigger_restart_framework ซึ่งจะดำเนินขั้นตอนการเปิดเครื่องตามปกติต่อไป

เข้ารหัสอุปกรณ์ที่มีอยู่

การดำเนินการนี้จะมีผลเมื่อคุณเข้ารหัสอุปกรณ์ Android K หรือเก่ากว่าที่ไม่ได้เข้ารหัสซึ่งย้ายข้อมูลไปยัง L แล้ว

กระบวนการนี้เริ่มต้นโดยผู้ใช้ และในโค้ดจะเรียกว่า "การเข้ารหัสภายใน" เมื่อผู้ใช้เลือกที่จะเข้ารหัสอุปกรณ์ UI จะตรวจสอบว่าแบตเตอรี่ชาร์จเต็มแล้วและเสียบปลั๊กอะแดปเตอร์ AC เพื่อให้มีพลังงานเพียงพอสำหรับขั้นตอนการเข้ารหัสให้เสร็จสิ้น

คำเตือน: หากแบตเตอรี่ของอุปกรณ์หมดและปิดไปก่อนการเข้ารหัสเสร็จสิ้น ข้อมูลไฟล์จะยังคงอยู่ในสถานะที่เข้ารหัสบางส่วน อุปกรณ์ต้องรีเซ็ตเป็นค่าเริ่มต้นและข้อมูลทั้งหมดจะหายไป

หากต้องการเปิดใช้การเข้ารหัสแบบอินเทอร์แอ็กทีฟ vold จะเริ่มวนซ้ำเพื่ออ่านแต่ละส่วนของอุปกรณ์บล็อกจริง จากนั้นเขียนลงในอุปกรณ์บล็อกคริปโต vold จะตรวจสอบว่าเซกเตอร์มีการใช้งานอยู่หรือไม่ก่อนที่จะอ่านและเขียน ซึ่งทำให้การเข้ารหัสเร็วขึ้นมากในอุปกรณ์ใหม่ที่มีข้อมูลน้อยหรือไม่มีข้อมูล

สถานะของอุปกรณ์: ตั้งค่า ro.crypto.state = "unencrypted" และเรียกใช้ทริกเกอร์ on nonencrypted init เพื่อบูตต่อ

  1. ตรวจสอบรหัสผ่าน

    UI จะเรียก vold ด้วยคําสั่ง cryptfs enablecrypto inplace โดยที่ passwd คือรหัสผ่านหน้าจอล็อกของผู้ใช้

  2. ลบเฟรมเวิร์กออก

    vold จะตรวจสอบข้อผิดพลาด แสดงผล -1 หากเข้ารหัสไม่ได้ และพิมพ์เหตุผลในบันทึก หากเข้ารหัสได้ ระบบจะตั้งค่าพร็อพเพอร์ตี้ vold.decrypt เป็น trigger_shutdown_framework การดำเนินการนี้จะทำให้ init.rc หยุดบริการในชั้นเรียน late_start และ main

  3. สร้างส่วนท้ายเกี่ยวกับคริปโต
  4. สร้างไฟล์เบรดครัมบ์
  5. รีบูต
  6. ตรวจหาไฟล์เบรดครัมบ์
  7. เริ่มเข้ารหัส /data

    vold จะตั้งค่าการแมปการเข้ารหัส ซึ่งจะสร้างอุปกรณ์บล็อกการเข้ารหัสเสมือนจริงที่แมปกับอุปกรณ์บล็อกจริง แต่เข้ารหัสแต่ละภาคขณะเขียน และถอดรหัสแต่ละภาคขณะอ่าน จากนั้น vold จะสร้างและเขียน ข้อมูลเมตาของคริปโต

  8. ขณะเข้ารหัส ให้ต่อเชื่อม tmpfs

    vold ต่อเชื่อม tmpfs /data (โดยใช้ตัวเลือก tmpfs จาก ro.crypto.tmpfs_options) และตั้งค่าพร็อพเพอร์ตี้ vold.encrypt_progress เป็น 0 vold เตรียม tmpfs /data สําหรับการบูตระบบที่เข้ารหัสและตั้งค่าพร็อพเพอร์ตี้ vold.decrypt เป็น trigger_restart_min_framework

  9. แสดงเฟรมเวิร์กเพื่อแสดงความคืบหน้า

    trigger_restart_min_framework ทําให้ init.rc เริ่มบริการระดับ main เมื่อเฟรมเวิร์กเห็นว่า vold.encrypt_progress มีการตั้งค่าเป็น 0 ระบบจะแสดง UI ของแถบความคืบหน้า ซึ่งจะค้นหาพร็อพเพอร์ตี้ทุกๆ 5 วินาทีและอัปเดตแถบความคืบหน้า ลูปการเข้ารหัสจะอัปเดต vold.encrypt_progress ทุกครั้งที่เข้ารหัสอีกเปอร์เซ็นต์หนึ่งของพาร์ติชัน

  10. เมื่อ /data ได้รับการเข้ารหัส ให้อัปเดตส่วนท้ายการเข้ารหัส

    เมื่อเข้ารหัส /data เรียบร้อยแล้ว vold จะล้างแฟล็ก ENCRYPTION_IN_PROGRESS ในข้อมูลเมตา

    เมื่ออุปกรณ์ปลดล็อกสำเร็จแล้ว ระบบจะใช้รหัสผ่านเพื่อเข้ารหัสคีย์หลักและส่วนท้ายของคริปโตได้รับการอัปเดต

    หากการรีบูตไม่สำเร็จด้วยเหตุผลบางประการ vold จะตั้งค่าพร็อพเพอร์ตี้ vold.encrypt_progress เป็น error_reboot_failed และ UI ควรแสดงข้อความที่ขอให้ผู้ใช้กดปุ่มเพื่อรีบูต ซึ่งไม่ควรเกิดขึ้น

เริ่มอุปกรณ์ที่เข้ารหัสด้วยการเข้ารหัสเริ่มต้น

เหตุการณ์นี้จะเกิดขึ้นเมื่อคุณบูตอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสเมื่อบูตเครื่องครั้งแรก จึงไม่ควรมีการตั้งรหัสผ่าน และนี่คือสถานะการเข้ารหัสเริ่มต้น

  1. ตรวจหา /data ที่เข้ารหัสโดยไม่มีรหัสผ่าน

    ตรวจพบว่าอุปกรณ์ Android มีการเข้ารหัสเนื่องจากติดตั้ง /data ไม่ได้และมีการตั้งค่า Flag encryptable หรือ forceencrypt ไว้รายการใดรายการหนึ่งแล้ว

    vold ตั้งค่า vold.decrypt เป็น trigger_default_encryption ซึ่งจะเริ่มต้นบริการ defaultcrypto trigger_default_encryption จะตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า /data เข้ารหัสโดยมีหรือไม่มีรหัสผ่าน

  2. Decrypt /data

    สร้างอุปกรณ์ dm-crypt บนอุปกรณ์บล็อกเพื่อให้อุปกรณ์พร้อมใช้งาน

  3. ต่อเชื่อม /ข้อมูล

    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 เป็นครั้งแรกตั้งแต่เปิดเครื่องด้วย

  4. Start Framework

    ตอนนี้เฟรมเวิร์กจะบูตบริการทั้งหมดโดยใช้ /data ที่ถอดรหัสแล้ว และระบบก็พร้อมใช้งาน

เริ่มใช้อุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น

สิ่งที่จะเกิดขึ้นเมื่อคุณบูตอุปกรณ์ที่เข้ารหัสซึ่งมีการตั้งรหัสผ่านไว้ รหัสผ่านของอุปกรณ์อาจเป็น PIN, รูปแบบ หรือรหัสผ่าน

  1. ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน

    ตรวจพบว่าอุปกรณ์ Android ได้รับการเข้ารหัสเนื่องจาก Flag ro.crypto.state = "encrypted"

    vold ตั้งค่า vold.decrypt เป็น trigger_restart_min_framework เนื่องจาก /data เข้ารหัสด้วยรหัสผ่าน

  2. ต่อเชื่อม tmpfs

    init กำหนดพร็อพเพอร์ตี้ 5 รายการเพื่อบันทึกตัวเลือกการต่อเชื่อมเริ่มต้นที่ใช้กับ /data ซึ่งมีพารามิเตอร์ที่ส่งจาก init.rc vold ใช้พร็อพเพอร์ตี้เหล่านี้ในการตั้งค่าการแมปคริปโต

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (ตัวเลขฐาน 16 8 หลักของ ASCII ตามด้วย 0x)
  3. เริ่มเฟรมเวิร์กเพื่อแจ้งให้ป้อนรหัสผ่าน

    เฟรมเวิร์กเริ่มต้นขึ้นและเห็นว่าตั้งค่า vold.decrypt เป็น trigger_restart_min_framework ซึ่งจะบอกเฟรมเวิร์กว่ากำลังบูตในดิสก์ tmpfs /data และต้องได้รับรหัสผ่านของผู้ใช้

    อย่างไรก็ตาม อันดับแรกต้องตรวจสอบว่าดิสก์ได้รับการเข้ารหัสอย่างถูกต้อง ซึ่งจะส่งคำสั่ง cryptfs cryptocomplete ไปยัง vold vold จะแสดงผลเป็น 0 หากการเข้ารหัสเสร็จสมบูรณ์ -1 หากมีข้อผิดพลาดภายใน หรือ -2 หากการเข้ารหัสไม่เสร็จสมบูรณ์ vold จะระบุข้อมูลนี้โดยดูที่ธง CRYPTO_ENCRYPTION_IN_PROGRESS ในข้อมูลเมตาของคริปโต หากตั้งค่าไว้ ขั้นตอนการเข้ารหัสจะหยุดชะงักและไม่มีข้อมูลที่ใช้งานได้ในอุปกรณ์ หาก vold แสดงข้อผิดพลาด UI ควรแสดงข้อความให้ผู้ใช้รีบูตและรีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น รวมถึงแสดงปุ่มให้ผู้ใช้กดเพื่อดำเนินการดังกล่าว

  4. ถอดรหัสข้อมูลด้วยรหัสผ่าน

    เมื่อ cryptfs cryptocomplete ดำเนินการเสร็จสมบูรณ์แล้ว เฟรมเวิร์กจะแสดง UI เพื่อขอรหัสผ่านของดิสก์ UI จะตรวจสอบรหัสผ่านโดยส่งคำสั่ง cryptfs checkpw ไปยัง vold หากรหัสผ่านถูกต้อง (ซึ่งพิจารณาจากการต่อเชื่อม/dataที่ถอดรหัสแล้วในตำแหน่งชั่วคราวและถอดออกเรียบร้อยแล้ว) vold จะบันทึกชื่ออุปกรณ์บล็อกที่ถอดรหัสแล้วในพร็อพเพอร์ตี้ ro.crypto.fs_crypto_blkdev และแสดงสถานะ 0 ไปยัง UI หากรหัสผ่านไม่ถูกต้อง ระบบจะแสดงค่า -1 ใน UI

  5. เฟรมเวิร์กการหยุด

    UI สร้างกราฟิกเปิดเครื่องคริปโตแล้วเรียกใช้ vold ด้วยคำสั่ง cryptfs restart vold จะตั้งค่าพร็อพเพอร์ตี้ vold.decrypt เป็น trigger_reset_main ซึ่งทำให้ init.rc ทำงาน class_reset main ซึ่งจะหยุดบริการทั้งหมดในคลาสหลัก ซึ่งจะช่วยให้ยกเลิกการต่อเชื่อม tmpfs /data ได้

  6. 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 เป็นครั้งแรกตั้งแต่เปิดเครื่องด้วย

  7. เริ่มใช้งานเฟรมเวิร์กแบบสมบูรณ์

    ตอนนี้เฟรมเวิร์กจะบูตบริการทั้งหมดโดยใช้/data ระบบไฟล์ที่ถอดรหัสแล้ว และระบบก็พร้อมใช้งาน

ไม่สำเร็จ

อุปกรณ์ที่ถอดรหัสไม่สำเร็จอาจมีปัญหาอยู่ 2-3 อย่าง อุปกรณ์จะเริ่มด้วยขั้นตอนชุดปกติในการเปิดเครื่องดังนี้

  1. ตรวจหาอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
  2. ต่อเชื่อม tmpfs
  3. เริ่มเฟรมเวิร์กเพื่อแจ้งให้ป้อนรหัสผ่าน

แต่หลังจากเปิดเฟรมเวิร์กแล้ว อุปกรณ์อาจพบข้อผิดพลาดบางอย่าง ดังนี้

  • รหัสผ่านตรงกันแต่ถอดรหัสข้อมูลไม่ได้
  • ผู้ใช้ป้อนรหัสผ่านผิด 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 ครั้ง จากนั้นระบบจะใช้คีย์นี้เพื่อเข้ารหัสและถอดรหัสคีย์หลัก วิธีจัดเก็บคีย์นี้

  1. สร้างคีย์การเข้ารหัสดิสก์ 16 ไบต์แบบสุ่ม (DEK) และ Salt 16 ไบต์
  2. ใช้สคริปต์กับรหัสผ่านผู้ใช้และ Salt เพื่อสร้างคีย์กลางขนาด 32 ไบต์ 1 (IK1)
  3. แพด IK1 ที่มีขนาด 0 ไบต์ตามขนาดของคีย์ส่วนตัวที่ผูกกับฮาร์ดแวร์ (HBK) กล่าวอย่างเจาะจงคือ เรากำหนดเป็น 00 || IK1 || 00..00; 1 ไบต์, 32 IK1 ไบต์, 223 ศูนย์ไบต์
  4. เซ็นชื่อ IK1 ที่เพิ่มความหนาด้วย HBK เพื่อสร้าง IK2 ขนาด 256 ไบต์
  5. ใช้การเข้ารหัสกับ IK2 และ Salt (เกลือเดียวกับขั้นตอนที่ 2) เพื่อสร้าง IK3 ขนาด 32 ไบต์
  6. ใช้ 16 ไบต์แรกของ IK3 เป็น KEK และ 16 ไบต์สุดท้ายเป็น IV
  7. เข้ารหัส 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 ที่เข้ารหัส

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

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