全磁碟加密是使用 加密金鑰裝置經過加密後,所有使用者建立的資料都會受到 自動加密後再將檔案提交至磁碟和所有讀取作業 就會自動解密資料,再將資料傳回呼叫程序。
Android 是在 4.4 版中加入全磁碟加密功能,Android 5.0 才推出這項功能 這些新功能:
- 建立快速加密,只對已使用的資料分區加密的區塊加密 可避免初次啟動花費太多時間僅限 ext4 和 f2fs 檔案系統 請注意,目前也支援快速加密
- 已新增
forceencrypt
fstab 旗標,藉此在首次啟動時加密。 - 開始支援無密碼的模式和加密功能。
- 新增採用「可信任」機制的加密金鑰儲存空間硬體支援儲存空間 執行環境 (TEE) 簽署能力 (例如 TrustZone 中)。 詳情請參閱儲存加密金鑰 詳細資料。
注意:先升級至 Android 5.0 的裝置 恢復原廠設定後,任何加密狀態可能會還原為未加密狀態。全新 Android 5.0 無法在首次啟動時加密的裝置回到未加密狀態。
Android 全磁碟加密功能的運作方式
Android 全磁碟加密是以 dm-crypt
為基礎,這是核心
可以在封鎖裝置層運作因為
加密技術適用於內嵌式 MultiMediaCard (eMMC) 和
自行在核心中顯示為區塊的類似 Flash 裝置
裝置。YAFFS 無法直接加密原始模型,
NAND 快閃晶片。
加密演算法採用 128 Advanced Encryption Standard (AES), 加密區塊鏈結 (CBC) 和 ESSIV:SHA256。主要金鑰是以 128 位元 AES,透過呼叫 OpenSSL 程式庫。您必須使用 128 位元以上的 鍵 (256 為選用)。
注意:原始設備製造商 (OEM) 可使用 128 位元以上將主金鑰加密。
在 Android 5.0 版本中,有四種加密狀態:
- 預設
- PIN 碼
- 密碼
- 圖案
初次啟動時,裝置會建立隨機產生的 128 位元主金鑰 然後使用預設密碼和儲存的鹽字串進行雜湊處理。預設密碼為:「default_password」 不過,結果雜湊會透過 TEE (例如 TrustZone) 簽署。 使用簽章的雜湊值加密主金鑰。
您可以在 Android 開放原始碼計畫 cryptfs.cpp 中找到定義的預設密碼 檔案。
使用者在裝置上設定 PIN 碼/密碼或密碼時,只能輸入 128 位元金鑰 會重新加密並儲存(也就是說,使用者 PIN 碼/票證/圖案變更並「不會」造成原因) 重新加密使用者資料)。請注意, 受管理的裝置 可能受到 PIN 碼、解鎖圖案或密碼的限制。
加密功能是由「init
」和「vold
」管理。
init
呼叫 vold
,而且 vold 集會觸發要觸發的屬性
初始化事件。系統的其他部分
也會檢視資源來執行報表狀態等工作
密碼。如果發生重大錯誤,手機會提示遭恢復原廠設定。叫用
加密功能,系統將會使用指令列工具 (vold
)
vdc
的 cryptfs
指令: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
。
以下詳細說明每個流程。
使用強制加密功能加密新裝置
這是 Android 5.0 裝置的一般啟動程序。
- 使用
forceencrypt
旗標偵測未加密的檔案系統/data
未加密,但必須負起「forceencrypt
」的規定。 卸載/data
。 - 開始加密
/data
vold.decrypt = "trigger_encryption"
觸發了init.rc
, 因此vold
會在不使用密碼的情況下為/data
加密。 (未設定,因為這應該是新裝置)。 - 掛接 tmpfs
vold
會掛接 tmpfs/data
(使用ro.crypto.tmpfs_options
),並將vold.encrypt_progress
屬性設為 0。vold
準備 tmpfs/data
來啟動加密系統,並設定 資源「vold.decrypt
」改為:trigger_restart_min_framework
- 建立架構以顯示進度
由於裝置幾乎沒有可加密的資料,因此進度列會顯示 但通常不會實際顯示,因為加密速度非常快。詳情請見 將現有裝置加密以瞭解詳情 進度 UI 的詳細資料
- 在
/data
加密之後,移除架構vold
將vold.decrypt
設為trigger_default_encryption
,這會啟動 「defaultcrypto
」服務。(系統會開始下列流程來掛接 預設加密使用者資料)。trigger_default_encryption
會檢查 加密類型,檢查/data
是否使用 密碼。由於 Android 5.0 裝置會在首次啟動時加密,因此應有 未設定密碼;因此我們會解密並掛接/data
。 - 掛接
/data
init
接著使用以下程式碼,在 tmpfs RAMDisk 上掛接/data
: 系統從ro.crypto.tmpfs_options
擷取的參數 位置:init.rc
。 - 開始使用架構
vold
將vold.decrypt
設為trigger_restart_framework
,會繼續正常啟動 上傳資料集之後,您可以運用 AutoML 自動完成部分資料準備工作
加密現有裝置
將未加密的 Android K 以下版本加密,會有什麼影響? 已轉移到 L 的裝置。
這項程序是由使用者所啟動,在 程式碼使用者選擇加密裝置時,UI 會確保 電池已充飽電,且 AC 變壓器已接上電源,確保有足夠的電力 才能完成加密程序。
警告:裝置沒電,並在結束前關機 加密時,檔案資料會處於部分加密狀態。裝置必須 恢復原廠設定,所有資料都遺失。
如要啟用內置加密,vold
會啟動迴圈讀取每個機制
然後將解碼器寫入
傳送至加密區塊裝置vold
會檢查特定產業是否位於
讀取及寫入資料
在新裝置上加密的效率大幅提升。
裝置狀態:設定 ro.crypto.state = "unencrypted"
然後執行 on nonencrypted
init
觸發條件來繼續啟動程序。
- 檢查密碼
UI 會使用
cryptfs enablecrypto inplace
指令呼叫vold
其中passwd
是使用者的螢幕鎖定密碼。 - 移除架構
vold
會檢查錯誤,如果無法加密,則會傳回 -1;以及 在記錄中顯示原因。如果可加密,則會設定vold.decrypt
屬性。 至trigger_shutdown_framework
。這會導致init.rc
停止在late_start
和main
類別中提供服務。 - 建立加密頁尾
- 建立導覽標記檔案
- 重新啟動
- 偵測導覽標記檔案
- 開始加密
/data
vold
會設定加密編譯對應關係,以便建立虛擬加密區塊裝置 會對應至真實區塊裝置,但會在寫入每個部門時加密, 讀取及解密每個向量。vold
接著會建立並寫入 加密編譯中繼資料 - 在加密時,掛接 tmpfs
vold
會掛接 tmpfs/data
(使用 tmpfs 選項) ,並設定屬性:ro.crypto.tmpfs_options
vold.encrypt_progress
到 0。vold
負責準備 tmpfs/data
用於啟動加密系統並設定屬性vold.decrypt
變更為:trigger_restart_min_framework
- 建立架構以顯示進度
trigger_restart_min_framework
造成init.rc
: 啟動main
服務類別。架構發現 如果將vold.encrypt_progress
設為 0,系統就會顯示進度列 UI,會每隔五秒就查詢該屬性,並更新進度列。 加密迴圈每次都會更新vold.encrypt_progress
則會加密另一個百分比的分區。 - 將
/data
加密後,請更新加密頁尾/data
成功加密後,vold
就會清除 在中繼資料中加入旗標ENCRYPTION_IN_PROGRESS
。成功解鎖裝置後,即可使用密碼 加密主要金鑰,加密頁尾已更新。
如果因故重新啟動失敗,
vold
會設定屬性vold.encrypt_progress
到error_reboot_failed
和 UI 應顯示訊息,要求使用者按下按鈕 。請放心,這種錯誤不會發生。
啟動使用預設加密機制的加密裝置
如果在沒有密碼的情況下啟動加密裝置,就會發生這種情形。 由於 Android 5.0 裝置會在首次啟動時加密,因此不應有任何設定 因此此為預設加密狀態。
- 偵測無密碼的已加密
/data
偵測 Android 裝置是否已加密,原因如下:
/data
無法掛接,且其中一個旗標encryptable
或forceencrypt
已設定。vold
將vold.decrypt
設為trigger_default_encryption
,從 「defaultcrypto
」服務。trigger_default_encryption
檢查加密類型,確認/data
是否已為 不需要密碼 - 解密 /資料
透過區塊裝置建立
dm-crypt
裝置,確保裝置 立即可用 - 掛接 /資料
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
類別中啟動服務,第一個使用 所花費的時間。 - 開始使用架構
現在架構會使用解密的
/data
啟動所有服務。 且系統也準備就緒可供使用
啟動未採用預設加密機制的加密裝置
啟用設有 密碼。裝置的密碼可以是 PIN 碼、解鎖圖案或密碼。
- 使用密碼偵測已加密的裝置
偵測 Android 裝置因標記而已加密
ro.crypto.state = "encrypted"
vold
將vold.decrypt
設為trigger_restart_min_framework
,因為/data
是 使用密碼加密 - 掛接 tmpfs
init
會設定五項屬性儲存初始掛接選項 為/data
提供,且其參數是從init.rc
傳遞。vold
會利用下列屬性設定加密編譯對應:ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(ASCII 8 位數十六進位數字,前面加上 0x)
- 開始架構以提示密碼
架構會啟動,並發現
vold.decrypt
已設為trigger_restart_min_framework
。讓架構機構知道 在 tmpfs/data
磁碟上開機,該磁碟需要取得使用者密碼。不過,首先必須確認磁碟已妥善加密。這項服務 傳送
cryptfs cryptocomplete
指令至vold
。 如果加密順利完成,vold
會傳回 0;發生內部錯誤時會傳回 -1;或 -2 表示加密未順利完成。vold
:決定 藉由查看CRYPTO_ENCRYPTION_IN_PROGRESS
的加密中繼資料 旗標。如果設定這項政策,加密程序就會中斷,而且未發生 裝置可用的資料如果vold
傳回錯誤,UI 應該 顯示訊息向使用者顯示重新啟動裝置、將裝置恢復原廠設定,然後 而使用者按下該按鈕進行這類操作 - 使用密碼解密資料
cryptfs cryptocomplete
成功後,架構 會顯示一個 UI,要求提供磁碟密碼。UI 會藉由 傳送cryptfs checkpw
指令至vold
。如果 密碼正確 (由成功掛接的 已在臨時位置解密/data
,然後將其卸載);vold
會將已解密的封鎖裝置名稱儲存在屬性中ro.crypto.fs_crypto_blkdev
且將狀態 0 傳回 UI。如果 密碼不正確,UI 會傳回 -1。 - 停止架構
UI 會顯示加密啟動圖形,然後利用以下內容呼叫
vold
: 輸入cryptfs restart
指令vold
會設定屬性vold.decrypt
到trigger_reset_main
,這會導致 需init.rc
執行class_reset main
。這會停止所有服務 位於主要類別中,這可讓系統卸載 tmpfs/data
。 - 掛接
/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
表示開機後第一次使用。 - 開始使用完整架構
現在架構會使用解密的
/data
啟動所有服務 即可開始使用
失敗
無法解密的裝置可能會因某些原因而產生故障。裝置 請從一般的啟動步驟開始:
- 使用密碼偵測已加密的裝置
- 掛接 tmpfs
- 開始建立提示以輸入密碼
但架構開啟後,裝置可能會發生一些錯誤:
- 密碼相符,但無法解密資料
- 使用者輸入錯誤密碼 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) 簽署功能實作。 我們先前是使用套用加密機制所產生的金鑰來加密主金鑰 密碼和資料儲存的鹽。為了確保金鑰的彈性 藉由簽署最終金鑰來擴充這個演算法 擷取 TEE 金鑰然後,產生的簽章會轉換成適當的 再套用一次 scrypt這組金鑰接著會用於加密 並解密主金鑰。如何儲存這組金鑰:
- 隨機產生 16 位元組磁碟加密金鑰 (DEK) 和 16 位元組的鹽。
- 為使用者密碼和鹽,產生 32 位元組的中繼資訊 鍵 1 (IK1)。
- 為硬體繫結私密金鑰 (HBK) 大小提供零位元組的 Pad IK1。 具體而言,我們會調成:00 ||IK1 ||00..00;一個零位元組、32 IK1 個位元組、223 零位元組
- 使用 HBK 簽署已填充的 IK1,以產生 256 位元組的 IK2。
- 套用 IK2 和鹽 (與步驟 2 相同的鹽) 以產生 32 位元組 IK3。
- 使用 IK3 的前 16 個位元組做為 KEK,最後一個 16 個位元組做為 IV。
- 使用 AES_CBC 加密 DEK,並使用金鑰 KEK 和初始化向量 IV 加密。
變更密碼
使用者在設定中選擇變更或移除密碼時,使用者介面會傳送
將 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 |
設為關閉要求提供磁碟密碼的 UI。 |
vold.decrypt trigger_post_fs_data |
設定前提為 /data 準備必要的目錄等等。 |
vold.decrypt trigger_restart_framework |
由 轉變為啟動實際架構和所有服務。 |
vold.decrypt trigger_shutdown_framework |
設為關閉完整架構,啟動加密作業。 |
vold.decrypt trigger_restart_min_framework |
設定到啟動
加密進度列 UI
提示輸入密碼
ro.crypto.state 的值。 |
vold.encrypt_progress |
架構啟動後 如果已設定此屬性,請輸入 進度列 UI 模式 |
vold.encrypt_progress 0 to 100 |
進度列 UI 應該 就會顯示設定的百分比值 |
vold.encrypt_progress error_partially_encrypted |
進度列使用者介面應會顯示加密失敗的訊息, 為使用者提供 將裝置恢復原廠設定。 |
vold.encrypt_progress error_reboot_failed |
進度列 UI 應顯示加密訊息 完成後,請提供可重新啟動裝置的按鈕。這個錯誤 表示無需發生 |
vold.encrypt_progress error_not_encrypted |
進度列 UI 應該 顯示錯誤訊息。 發生、未加密任何資料,或 ,並為使用者提供重新啟動系統的按鈕。 |
vold.encrypt_progress error_shutting_down |
進度列使用者介面並未執行,因此無法確定回應者是誰 。而這個情況應該永遠不會發生。 |
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 運作。 |
|
這五項屬性
當伺服器嘗試透過傳入的參數掛接 /data 時,系統會傳回 init
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