Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android全磁盤加密

android全磁盤加密

編輯:關於Android編程

什麼是全磁盤加密?


全磁盤加密是使用一個密鑰來為android設備上所有的用戶數據加密的過程。一旦設備被加密,所有的用戶創建的數據都將會在提交的磁盤之前自動加密,在讀取之前都會自動解密。

Android 5.0中添加了啥
創建了快速加密,該加密方式僅僅加密在數據分區中使用塊設備的數據來避免第一次啟動耗費較長時間。僅僅ext4和f2fs文件系統支持快速加密。
在首次啟動的時候添加forceencrypt標志來加密增加了對模式的支持和沒有密碼的加密增加使用可信執行環境的密鑰的硬件支持存儲。

注意:升級到Android5.0並且被加密的設備可能會數據恢復出廠後返回一個未加密狀態。在首次啟動時加密的新的Android 5.0設備不能返回到未加密狀態。


Android全磁盤加密是如何工作的

Android全磁盤加密基於dm-crypy,他是一個內核特征,工作在塊設備層。出於這個原因,加密是和嵌入式多媒體卡和作為塊設備的閃存設備一起工作的。在YAFFS文件系統中,加密是不可能工作的,他是直接和NAND閃存芯片工作的。

加密算法是帶有CBC和 ESSIV:SHA256的128高級加密標准。主鍵是通過128位AES通過OpenSSL庫被加密的。你必須要使用128位或更大位數的鍵值。

注意:OEMs能夠使用128位或更高位數來加密主鍵。

在Android5.0的發行版中,有四種加密狀態:

默認PIN密碼模式

在第一次啟動的時候,設備創建一個隨機生成的128位主鍵,然後使用默認密碼和存儲的salt進行哈希運算。默認密碼是”default_password”。然而,結果散列也需要通過TEE進行簽名,他使用一個簽名的散列來加密主鍵。

你可以在Android源碼文件cryptfs.c中找到默認密碼。

當用戶在設備中設置了PIN或者是密碼,僅僅128位的鍵被重新加密和存儲。(用戶PIN/密碼/模式的改變不會造成用戶數據重新加密)。注意管理的設備可能會受到PIN,模式或密碼的限制。

加密是由init和vold管理的。init調用vold,vold設置位於init中的屬性來觸發事件。系統的其他部分也會根據這些屬性來進行工作,例如報告狀態,查詢密碼,或者是發生致命錯誤的時候及時工廠重置。為了在vold中激活加密特征,系統使用命令行工具vdc’s cryptfs運行命令: checkpw, restart, enablecrypto, changepw, cryptocomplete, verifypw,setfield, getfield, mountdefaultencrypted, getpwtype, getpw, 和clearpw.

為了進行加密,解密或清除/data,/data必須要被掛載。然而,為了能夠顯示用戶接口,框架一定要運行並且框架需要/data來運行。為了解決這個難題,在/data中會掛載一個臨時的文件系統。這使得安卓能夠提示密碼,顯示進展,或在需要的時候進行數據擦除。在從臨時文件系統到真實的/data文件系統的轉換的時候強加了一些限制,系統必須要停止打開臨時文件系統中文件的每一個進程,然後在真實的/data文件系統中重啟這些進程。為了這樣做,所有的服務都必須在這三個組中的一個中:core,main和late_start。

core:在啟動後永遠不關閉main:在磁盤密碼輸入後關機在重啟late_restart:在/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設備正常的首次啟動。

檢測到帶有/forceencrypt標志的未加密文件系統

 

/data沒有被加密,但是必須要進行加密。因為 /forceencrypt委托他這樣做。卸載/data

開始加密/data

 

vold.decrypt = "trigger_encryption" triggers init.rc, which will cause vold to encrypt /data with no password. (None is set because this should be a new device.)

掛載tmpfs

vold掛載一個臨時文件系統 /data(從ro.crypto.tmpfs_options中使用tmpfs選項),並且設置屬性vold.encrypt_progress 為0.vold為啟動一個加密的系統准備tmpfs /data,並且設置屬性vold.decrypt為trigger_restart_min_framework

提出框架,顯示進度

因為該設備幾乎沒有數據去加密了,進度條也不會顯示了,因為加密過程會很快。

當/data被加密之後,卸下框架

vold設置vold.decrypt為 開始defaultcrypto 服務的trigger_default_encryption。(這個會開始下面的流用於掛載一個默認的加密用戶數據)。trigger_default_encryption檢查加密類型來查看/data是否是帶有密碼被加密的。因為Android5.0設備在首次啟動的時候被加密,應該沒有密碼設置;因此我們解密並且掛載/data。

掛載/data

init然後使用從ro.crypto.tmpfs_options中選出的參數在tmpfs的RAMDisk 中掛載/data,ro.crypto.tmpfs_options是在init.rc中被設置的。

啟動框架

設置vold為trigger_restart_framework,他繼續常規的啟動進程。


加密一個現在的設備

這種情況發生在你加密一個未加密的Android k或更早版本的設備,該設備被一直到Android L的時候。注意,這個和在K中使用的流是一樣的。

這個進程是用戶初始化的,並且在代碼中被引用作為”就地加密”。當一個空戶選擇去加密一個設備的時候,UI確保電量是完全充電狀態並且AC適配器被插入,所以有足夠的變量來完成加密進程。

警告:如果設備在完成加密之前耗盡電量並且關機了,在部分加密狀態下會留下文件數據。設備必須要工廠重置,所有的數據都會丟失。

為了使能就地加密,vold開始一個循環來讀取真實塊設備的每一個扇區,然後將他寫到加密塊設備中。vold在讀取和寫數據之前,檢查扇區是否正在使用,這會使得在幾乎沒有數據的新設備上加密會很快。

 

設備狀態:設置ro.crypto.state = "unencrypted" 並且運行 on nonencrypted init觸發器來繼續啟動。

檢查密碼

UI在passwd是用戶鎖屏密碼的地方調用帶有命令cryptfs enablecrypto inplace的vold。

卸載框架

vold檢查錯誤,如果不能被加密,返回-1,並且在日志中打印原因。如果能夠加密,設置屬性 vold.decrypt為trigger_shutdown_framework。這會使init.rc停止位於類late_start和main中的服務。

卸載/data

vold卸載/mnt/sdcard,然後卸載/data。

開始加密/data

vold然後設置加密映射,該映射創建一個虛擬加密塊設備,該設備映射到真實的塊設備上,但是當寫入的時候加密每一個扇區,當讀取的時候解密每一個扇區。vold然後創建和編寫加密元數據。

當加密的時候,掛載tmpfs

vold掛載一個tmpfs /data(從ro.crypto.tmpfs_options中使用tmpfs選項),並且設置屬性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,他每5秒鐘查詢一下屬性然後更新進度條。每次他加密了一部分分區,加密程序就會更新 vold.encrypt_progress。

當/data被加密,重啟

當/data被成功加密了,vold會清除位於元數據中的標志ENCRYPTION_IN_PROGRESS,然後重啟。

如果某些原因重啟失敗,vold會設置屬性 vold.encrypt_progress為 error_reboot_failed,並且UI應該會展示一個信息詢問用戶按下按鈕重啟。這種情況永遠也不期望發生。

開啟一個帶有默認加密的加密設備

這種情況發生在當你想啟動一個沒有密碼的加密設備的時候。因為Android 5.0設備在首次啟動的時候被加密,應該沒有設置密碼,因此應該是默認加密狀態。

檢測加密的沒有密碼的/data

檢測Android設備已被加密,因為/data不能被掛載,並且標志flagsencryptable 或forceencrypt 之一被設置了。vold設置 vold.decrypt為

trigger_default_encryption,他用於啟動defaultcrypto 。trigger_default_encryption 檢查加密類型來查看/data有無密碼加密。

解密/data

在塊設備中,創建dm-crypt設備,所以設備已經可以使用。

掛載/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啟動所有他的服務,並且系統也可以正常使用了。

開啟一個不是默認加密的加密設備

這種情況發生在,當你啟動一個設置密碼的加密設備的時候。這個設備的密碼可以是pin,模式或密碼。

檢測帶有密碼的加密設備

檢測到Android設備被加密了,因為標志ro.crypto.state = “encrypted”

vold設置vold.decrypt為trigger_restart_min_framework,因為/data是使用密碼加密的。

掛載tmpfs

init設置下面5個屬性來保存初始化掛載選項,這些選項用於帶參數的/data。他們是從init.rc. vold中傳過來的,使用這些屬性來設置加密映射。

ro.crypto.fs_typero.crypto.fs_real_blkdevro.crypto.fs_mnt_pointro.crypto.fs_optionsro.crypto.fs_flags (ASCII 8-digit hex number preceded by 0x)啟動框架以提示輸入密碼

框架啟動,然後查看vold.decrypt是否被設置為 trigger_restart_min_framework。這告訴框架這是在tmpfs /data磁盤中啟動的,他需要獲取用戶密碼。

首先,他需要確定磁盤是否被正確加密。他發送命令cryptfs cryptocomplete到vold。如果加密完全成功,則返回0.如果內部錯誤,返回-1.或者是如果加密沒有完全成功返回-2。vold通過查看用於CRYPTO_ENCRYPTION_IN_PROGRESS標志的加密元數據來決定這個。如果被設置了,加密進程被中斷了,在設備中沒有可用的數據。如果vold返回一個錯誤,UI應該向用戶展示一個信息來重啟和工廠重置設備,並且給用戶一個按鈕來這樣做。

解密帶有密碼的數據

一旦cryptfs cryptocomplete成功了,框架就會展示一個UI詢問磁盤密碼。UI通過向vold發送命令cryptfs checkpw 來檢查密碼。如果密碼正確(這是由正確掛載到臨時位置的加密/data決定的,然後卸載塔),vold在屬性ro.crypto.fs_crypto_blkdev中保存解密塊設備的名稱,並且向UI返回狀態0.如果密碼不正確,向UI返回-1。

停止框架

UI彈出一個加密啟動圖形,然後使用命令 cryptfs restart. vold設置屬性vold.decrypt為trigger_reset_main來調用vold,這樣會使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提示用戶重啟,並且警告他們加密過程沒有開始。如果在框架卸下之後,在進度條開啟之前,錯誤發生了,vold將會重啟系統。如果重啟失敗,他會設置vold.encrypt_progress為error_shutting_down,並且返回-1;但是將不會有任何事情捕獲錯誤。這是不希望發生的。

如果vold在加密過程中檢測到一個錯誤,他會設置 vold.encrypt_progress為error_partially_encrypted,並且返回-1.UI應該會展示一個信息框說加密失敗,並且提供一個按鈕提示用戶恢復出廠重置設備。

存儲加密鍵

加密鍵值存儲在加密元數據中。硬件支持是通過使用可信環境簽名實現的。在以前,我們通過向用戶密碼和存儲salt應用scrypt來加密主鍵。為了使鍵抵抗攻擊,我們通過使用一個存儲的TEE鍵簽名一個組合鍵值來繼承他的算法。組合簽名通過一個scrypt的應用編程一個合適的密鑰長度。這個密鑰被使用去加密和解密主密鑰。下面是存儲這個密鑰的過程:

生成隨機16位的磁盤加密密鑰(DEK)和16為salt。向用戶密碼應用scrypt和salt來生成32位的中間密鑰1(IK1)。使用0填充IK1到硬件綁定私鑰(HBK)的大小。特別的,我們填充為: 00 || IK1 || 00..00;一個0位:32 IK1 bytes, 223 zero bytes.簽名帶有HBK的IK1來生成256位的IK2將scrypt應用到IK2和salt中來生成32為IK3使用IK3的前16位作為KEK,後16位作為IV加密帶有AES_CBS,帶有密鑰KEK的DEK,並且初始化向量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設置開始進度條來加密或者是提示用戶輸入密碼,依賴於ro.crypto.state的值 vold.encrypt_progress 當框架啟動的時候,如果這個屬性被設置,進入進度條模式 vold.encrypt_progress 0 to 100 進度條應該會展示百分值集合。 vold.encrypt_progress error_partially_encrypted 進度條應該展示一個加密失敗提示信息,並且給用戶一個選項來工廠重置設備。 vold.encrypt_progress error_reboot_failed 進度條應該顯示一個信息說加密完成,並且給用戶提供一個按鈕提示用戶重啟設備。這個錯誤我們不期望發生。 vold.encrypt_progress error_not_encrypted 進度條應該展示一個信息框說發生了一個錯誤,沒有數據被加密,並且給用戶一個按鈕提示用戶重啟系統。 vold.encrypt_progress error_shutting_down 進度條沒有運行,所以不清楚誰回應這個錯誤。他應該不會發生。 vold.post_fs_data_done 0 在設置vold.decrypt到trigger_post_fs_data之前由vold設置 vold.post_fs_data_done 1 在完成任務post-fs-data之後由init.rc設置

init屬性

屬性 描述 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.rc. vold中傳來的參數的/data的時候,這五個屬性由init設置來設置加密映射 ro.crypto.tmpfs_options 當掛載tmpfs /data文件系統的時候,由init.rc使用init應該使用的參數來設置。

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
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved