ฉันอ้างอิงจากคู่มือ Android ที่นี่แต่:
บันทึก:
แหล่งที่ฉันใช้ไม่เกี่ยวข้องโดยตรงกับ Marshmallow แต่เกี่ยวข้องกับ Lollipop และสูงกว่า
TL: DR
ฉันจะตอบคำถามของ OP ทันที รายละเอียดทางเทคนิคจะเป็นไปตาม
คีย์เข้ารหัสเริ่มต้นมาจากแหล่งฮาร์ดแวร์ (ชิปคล้ายกับ TPM) และรหัสผ่านเริ่มต้นของ AOSP ที่กำหนดไว้default_password
ในcryptfs.c
ไฟล์ต้นฉบับดูด้านล่าง
ใช่ไม่ใช่เฉพาะค่าเริ่มต้น แต่รหัสผ่านใด ๆ จะถูกสร้างขึ้นเป็นกุญแจและถูกเก็บไว้ในชิปที่คล้ายกับ TPM เรียกว่า TEE (ย่อมาจาก "Trusted Execution Environment" ดูรายละเอียดเพิ่มเติมด้านล่าง)
แฮ็กเกอร์ที่มีการเข้าถึง UART / JTAG เพื่อเข้าถึงชิปบน SoC ของอุปกรณ์สามารถเข้าถึงคีย์ TEE ในทางเทคนิคหรือเคอร์เนลแบบกำหนดเองสามารถรั่วไหลข้อมูลนี้ไปยังแฮ็กเกอร์ เอเจนซี 3 ตัวอักษรบางตัวในทฤษฎีสมคบคิดอาจร่วมมือกับ OEM เพื่อรับเมล็ดที่ไม่ปลอดภัยเหล่านี้ที่ใช้ในอุปกรณ์การผลิต แต่ฉันจะไม่วางร้านค้าจำนวนมาก ดูรายละเอียดเพิ่มเติมในส่วนสุดท้ายของคำตอบนี้
สิ่งเดียวที่ทำให้แฮ็กเกอร์ไม่สามารถเข้าถึงกุญแจได้คือความพยายามอย่างเต็มที่ในการทำเช่นนั้น
- การตรวจสอบของกัญชา (Checksumming) เฟิร์ม (เรียกว่า"Boot ที่ตรวจสอบแล้ว"โดย Google) ในความเป็นจริงทำบนและเหนืออมยิ้มโดยค่าเริ่มต้น (และสามารถใช้ได้จาก JellyBean 4.3 เป็นต้นไป)
dm-verity
โดยเคอร์เนลโมดูลที่เรียกว่า อย่างไรก็ตามนี่เป็นอิสระจากสถานะการเข้ารหัส
ที่มา:คู่มือการรักษาความปลอดภัย AOSP ที่นี่
- เกี่ยวกับกระบวนการที่เกี่ยวข้องกับการถอดรหัสระบบด้วยรหัสผ่านที่กำหนดเองดูด้านล่าง ฉันจะบอกคุณที่นี่ว่ารหัสผ่านผู้ใช้มีส่วนร่วมในการสร้างและการใช้งานคีย์เข้ารหัส
ภาพรวม
เมื่อทำการบู๊ตครั้งแรกอุปกรณ์จะสร้างคีย์หลักแบบ 128 บิตที่สร้างแบบสุ่มจากนั้นแฮชด้วยรหัสผ่านเริ่มต้นและเกลือที่เก็บไว้ รหัสผ่านเริ่มต้นคือ: "default_password" อย่างไรก็ตามแฮชที่เป็นผลลัพธ์จะถูกลงชื่อผ่าน TEE (เช่น TrustZone) ซึ่งใช้แฮชของลายเซ็นเพื่อเข้ารหัสคีย์หลัก
คุณสามารถค้นหารหัสผ่านเริ่มต้นที่กำหนดในไฟล์cryptfs.cโครงการ Android Open Source
เมื่อผู้ใช้ตั้งค่า PIN / รหัสผ่านหรือรหัสผ่านบนอุปกรณ์เฉพาะคีย์ 128 บิตเท่านั้นที่จะถูกเข้ารหัสและจัดเก็บใหม่ (เช่นการเปลี่ยนแปลง PIN ของผู้ใช้ / รหัสผ่าน / รูปแบบไม่ทำให้เกิดการเข้ารหัสลับของพาร์ติชัน userdata อีกครั้ง)
การเริ่มต้นอุปกรณ์ที่เข้ารหัสด้วยการเข้ารหัสเริ่มต้น
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณบูทอุปกรณ์ที่เข้ารหัสโดยไม่มีรหัสผ่าน เนื่องจากอุปกรณ์ Android 5.0 ได้รับการเข้ารหัสในการบู๊ตครั้งแรกจึงไม่ควรตั้งรหัสผ่านและนี่คือสถานะการเข้ารหัสเริ่มต้น
- ตรวจจับการเข้ารหัส / ข้อมูลโดยไม่มีรหัสผ่าน
ตรวจสอบว่าอุปกรณ์ Android ได้รับการเข้ารหัสเพราะ / data ไม่สามารถติดตั้งและตั้งค่าสถานะหนึ่งencryptable
หรือforceencrypt
ตั้งค่า
vold
กำหนดvold.decrypt
เป็นtrigger_default_encryption
ซึ่งจะเริ่มdefaultcrypto
บริการ trigger_default_encryption
ตรวจสอบประเภทการเข้ารหัสเพื่อดูว่า / data เข้ารหัสด้วยหรือไม่ใช้รหัสผ่าน
- ถอดรหัส / ข้อมูล
สร้างdm-crypt
อุปกรณ์ผ่านอุปกรณ์บล็อกเพื่อให้อุปกรณ์พร้อมใช้งาน
- เมานต์ / ข้อมูล
vold
จากนั้นเมานต์พาร์ติชั่นข้อมูลจริง / ถอดรหัสลับแล้วเตรียมพาร์ติชันใหม่ ได้กำหนดสถานที่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 เป็นครั้งแรกนับตั้งแต่เริ่มระบบ
- เริ่มกรอบงาน
ขณะนี้เฟรมเวิร์กบู๊ตบริการทั้งหมดโดยใช้การถอดรหัส / ข้อมูลและระบบพร้อมใช้งาน
การเริ่มต้นอุปกรณ์ที่เข้ารหัสโดยไม่มีการเข้ารหัสเริ่มต้น
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณบูทอุปกรณ์ที่เข้ารหัสซึ่งมีรหัสผ่านที่ตั้งไว้ รหัสผ่านของอุปกรณ์สามารถเป็นหมุดรูปแบบหรือรหัสผ่าน
- ตรวจจับอุปกรณ์ที่เข้ารหัสด้วยรหัสผ่าน
ตรวจสอบว่าอุปกรณ์ Android ถูกเข้ารหัสเพราะตั้งค่าสถานะ ro.crypto.state = "encrypted"
vold
ตั้งค่าvold.decrypt
เป็นtrigger_restart_min_framework
เพราะ / data ถูกเข้ารหัสด้วยรหัสผ่าน
- เมานต์ tmpfs
init
ชุดห้าคุณสมบัติเพื่อบันทึกตัวเลือกติดเบื้องต้นได้รับสำหรับ / init.rc
ข้อมูลที่มีค่าพารามิเตอร์ที่ส่งผ่านจาก vold
ใช้คุณสมบัติเหล่านี้เพื่อตั้งค่าการทำแผนที่ crypto:
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
ส่งคืน 0 หากการเข้ารหัสเสร็จสมบูรณ์แล้ว -1 ในข้อผิดพลาดภายในหรือ -2 ถ้าการเข้ารหัสไม่สำเร็จ กำหนดสิ่งนี้โดยดูในเมทาดาทา crypto เพื่อหาค่าสถานะ หากตั้งค่าไว้กระบวนการเข้ารหัสจะถูกขัดจังหวะและไม่มีข้อมูลที่ใช้งานได้บนอุปกรณ์vold
vold
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
สิ่งนี้จะหยุดบริการทั้งหมดในmain
คลาสซึ่งอนุญาตให้tmpfs /data
ยกเลิกการเมานท์
- เมานต์ / ข้อมูล
vold
จากนั้นเมาท์/data
พาร์ติชั่นที่ถอดรหัสแล้วและเตรียมพาร์ติชั่นใหม่ (ซึ่งอาจไม่เคยเตรียมมาหากมันถูกเข้ารหัสด้วยตัวเลือกการลบซึ่งไม่รองรับในรีลีสแรก) ได้กำหนดสถานที่vold.post_fs_data_done
ที่จะ0
แล้วชุดที่จะvold.decrypt
trigger_post_fs_data
นี่เป็นสาเหตุที่จะทำงานของมันinit.rc
post-fs-data commands
พวกเขาจะสร้างไดเรกทอรีที่จำเป็นใด ๆ หรือการเชื่อมโยงและจากนั้นตั้งค่าไปvold.post_fs_data_done
1
เมื่อvold
เห็น1
ในทรัพย์สินที่จะกำหนดสถานที่ที่จะvold.decrypt
trigger_restart_framework
ทำให้init.rc
การเริ่มบริการในคลาสmain
อีกครั้งและเริ่มบริการในคลาสlate_start
เป็นครั้งแรกนับตั้งแต่เริ่มระบบ
- เริ่มกรอบเต็ม
ขณะนี้เฟรมเวิร์กบู๊ตบริการทั้งหมดโดยใช้ระบบไฟล์ถอดรหัส / ข้อมูลและระบบพร้อมใช้งานแล้ว
การจัดเก็บคีย์เข้ารหัส
คีย์เข้ารหัสถูกเก็บไว้ในเมทาดาทา crypto การสำรองข้อมูลฮาร์ดแวร์ดำเนินการโดยใช้ความสามารถในการลงชื่อ (TEE) ของ Trusted Execution Environment ก่อนหน้านี้เราเข้ารหัสคีย์หลักด้วยรหัสที่สร้างขึ้นโดยใช้scrypt
กับรหัสผ่านของผู้ใช้และเกลือที่เก็บไว้
เพื่อที่จะทำให้คีย์ยืดหยุ่นจากการโจมตีนอกกล่องเราได้ขยายอัลกอริทึมนี้โดยการเซ็นชื่อคีย์ผลลัพธ์ด้วยคีย์ TEE ที่เก็บไว้ จากนั้นลายเซ็นผลลัพธ์จะกลายเป็นคีย์ความยาวที่เหมาะสมโดยแอปพลิเคชันอีกหนึ่งscrypt
รายการ คีย์นี้จะใช้ในการเข้ารหัสและถอดรหัสคีย์หลัก ในการจัดเก็บคีย์นี้:
- สร้างคีย์การเข้ารหัสดิสก์แบบสุ่มขนาด 16 ไบต์ (DEK) และเกลือขนาด 16 ไบต์
- นำ
scrypt
ไปใช้กับรหัสผ่านผู้ใช้และเกลือเพื่อสร้างคีย์กลาง 32- ไบต์ 1 (IK1)
- ผัด IK1 ที่มีค่าศูนย์ไบต์เท่ากับขนาดของคีย์ส่วนตัวที่ผูกไว้กับฮาร์ดแวร์ (HBK) เราเจาะจงเป็น: 00 || IK1 || 00..00; หนึ่งศูนย์ไบต์, 32 IK1 ไบต์, 223 ศูนย์ไบต์
- ลงนามเบาะ IK1 ด้วย HBK เพื่อสร้าง IK2 256- ไบต์
- นำ
scrypt
ไปใช้กับ IK2 และเกลือ (เกลือเดียวกับขั้นตอนที่ 2) เพื่อสร้าง IK3 ขนาด 32 ไบต์
- ใช้ 16 ไบต์แรกของ IK3 เป็น KEK และ 16 ไบต์สุดท้ายเป็น IV
- เข้ารหัส DEK ด้วย AES_CBC พร้อมคีย์ KEK และเวกเตอร์เริ่มต้น IV