ฉันอ้างอิงจากคู่มือ 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_done1
เมื่อ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 เพื่อหาค่าสถานะ หากตั้งค่าไว้กระบวนการเข้ารหัสจะถูกขัดจังหวะและไม่มีข้อมูลที่ใช้งานได้บนอุปกรณ์voldvoldvoldCRYPTO_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