การเข้ารหัสดิสก์ทั้งเครื่อง

การเข้ารหัสทั้งดิสก์คือกระบวนการเข้ารหัสข้อมูลผู้ใช้ทั้งหมดในอุปกรณ์ 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

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

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

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

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

  3. Mount 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 (ซึ่งจะเริ่มขั้นตอนด้านล่างสำหรับการติดตั้ง userdata ที่เข้ารหัสเริ่มต้น) trigger_default_encryption ตรวจสอบ ประเภทการเข้ารหัสเพื่อดูว่า /data เข้ารหัสโดยมีหรือไม่มี รหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 จะได้รับการเข้ารหัสเมื่อบูตครั้งแรก จึงไม่ควรมีการตั้งรหัสผ่าน ดังนั้นเราจึงถอดรหัสและติดตั้ง /data

  6. ติดตั้ง /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. สร้างไฟล์ Breadcrumb
  5. รีบูต
  6. ตรวจหาไฟล์เบรดครัมบ์
  7. เริ่มเข้ารหัส /data

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

  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 ทุกครั้งที่เข้ารหัสพาร์ติชันอีก 1%

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

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

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

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

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

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

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

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

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

  2. ถอดรหัส /data

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

  3. เมานต์ /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 เป็นครั้งแรก นับตั้งแต่เปิดเครื่อง

  4. เฟรมเวิร์กเริ่มต้น

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

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

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

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

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

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

  2. Mount 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 (เลขฐานสิบหก 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. ติดตั้ง /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 ที่ถอดรหัสแล้ว และระบบก็พร้อมใช้งาน

ไม่สำเร็จ

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

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

พร็อพเพอร์ตี้ทั้ง 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