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

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

  1. ตรวจจับระบบไฟล์ที่ไม่ได้เข้ารหัสด้วยแฟล็ก 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. เมานต์ /data

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

  7. เริ่มต้นกรอบงาน

    vold ตั้งค่า vold.decrypt เป็น trigger_restart_framework ซึ่งดำเนินกระบวนการบู๊ตตามปกติต่อไป

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

นี่คือสิ่งที่เกิดขึ้นเมื่อคุณเข้ารหัสอุปกรณ์ Android K หรือรุ่นก่อนหน้าที่ไม่ได้เข้ารหัสซึ่งย้ายไปยัง L

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

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

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

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

  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 จะตั้งค่าการทำแผนที่ crypto ซึ่งสร้างอุปกรณ์บล็อก crypto เสมือนที่แมปไปยังอุปกรณ์บล็อกจริง แต่จะเข้ารหัสแต่ละเซกเตอร์ตามที่เขียน และถอดรหัสแต่ละเซกเตอร์ในขณะที่อ่าน 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 ของแถบความคืบหน้าขึ้นมา ซึ่งจะสอบถามคุณสมบัตินั้นทุกๆ ห้าวินาที และอัปเดตแถบความคืบหน้า ลูปการเข้ารหัสจะอัปเดต vold.encrypt_progress ทุกครั้งที่เข้ารหัสอีกเปอร์เซ็นต์ของพาร์ติชัน

  10. เมื่อ /data ถูกเข้ารหัส ให้อัพเดตส่วนท้ายของ crypto

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

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

    หากการรีบูตล้มเหลวด้วยเหตุผลบางประการ 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. ถอดรหัส/ข้อมูล

    สร้างอุปกรณ์ 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.decrypt เป็น: trigger_restart_framework. สิ่งนี้ทำให้ init.rc เริ่มบริการในคลาส main อีกครั้ง และเริ่มบริการในคลาส late_start เป็นครั้งแรกนับตั้งแต่บูต

  4. เริ่มต้นกรอบงาน

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

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

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

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

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

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

  2. เมานต์ tmpfs

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

    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 (เลขฐานสิบหก ASCII 8 หลักนำหน้าด้วย 0x)
  3. เริ่มเฟรมเวิร์กเพื่อขอรหัสผ่าน

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

    อย่างไรก็ตาม ขั้นแรกต้องแน่ใจว่าดิสก์ได้รับการเข้ารหัสอย่างเหมาะสม มันส่งคำสั่ง cryptfs cryptocomplete ไปที่ vold vold ส่งคืน 0 หากการเข้ารหัสเสร็จสมบูรณ์ -1 สำหรับข้อผิดพลาดภายใน หรือ -2 หากการเข้ารหัสไม่เสร็จสมบูรณ์ vold กำหนดสิ่งนี้โดยดูในข้อมูลเมตาของ crypto สำหรับการตั้งค่าสถานะ 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 จะสร้างกราฟิกบูต crypto จากนั้นเรียกใช้ 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 ควรแสดงข้อความแจ้งว่าการเข้ารหัสล้มเหลว และให้ปุ่มให้ผู้ใช้รีเซ็ตอุปกรณ์เป็นค่าเริ่มต้น

การจัดเก็บคีย์ที่เข้ารหัส

คีย์ที่เข้ารหัสจะถูกจัดเก็บไว้ในข้อมูลเมตาของ crypto การสนับสนุนฮาร์ดแวร์ถูกนำมาใช้โดยใช้ความสามารถในการลงนามของ Trusted Execution Environment (TEE) ก่อนหน้านี้ เราได้เข้ารหัสคีย์หลักด้วยคีย์ที่สร้างขึ้นโดยใช้การเข้ารหัสกับรหัสผ่านของผู้ใช้และเกลือที่เก็บไว้ เพื่อให้คีย์มีความยืดหยุ่นต่อการโจมตีนอกกรอบ เราได้ขยายอัลกอริธึมนี้โดยการเซ็นชื่อคีย์ผลลัพธ์ด้วยคีย์ TEE ที่เก็บไว้ จากนั้นลายเซ็นที่เป็นผลลัพธ์จะถูกเปลี่ยนเป็นคีย์ความยาวที่เหมาะสมโดยการใช้สคริปต์อีกครั้งหนึ่ง จากนั้นคีย์นี้จะใช้ในการเข้ารหัสและถอดรหัสคีย์หลัก หากต้องการจัดเก็บคีย์นี้:

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

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

คุณสมบัติทั้งห้านี้ถูกตั้งค่าโดย 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