Android Gatekeeper流程深度解剖
快速鏈接:
.
👉👉👉 個人博客筆記導(dǎo)讀目錄(全部) 👈👈👈
相關(guān)推薦:
Android手機使用命令行增加/刪除/修改密碼(password/pin/pattern)
android密碼解鎖/指紋解鎖返回的authToken深度解剖
LockSettingsService的setLockCredentialInternal函數(shù)詳解
說明: 在無特別的說明下,本文講述得是android10.0 !
gatekeeper目錄
- 1、gatekeeper是什么?
- 2、gatekeeper的軟件框圖
- 3、enroll和verify的調(diào)用流程
- 4、重要的結(jié)構(gòu)體
- (1)、password_handle
- (2)、authToken
- 5、技術(shù)的細(xì)節(jié)
- (1)、failure_record :記錄失敗信息
- (2)、throttle : failed_counter和retry_time的規(guī)則
- (3)、timestamp
- a、在gatekeeper TA中的簡單合法校驗
- b、 在android中,會對timestamp進行檢查
- 6、關(guān)鍵函數(shù)的介紹
- LockSetting
- (1)、writeCredentialHash //將enroll_handle保存到文件
- Vendor Gatekeeper Hal
- (1)、enroll
- (2)、verify
1、gatekeeper是什么?
在android中,gatekeeper是密碼鎖或圖案鎖的一種服務(wù). 主要支持的兩個方法是:enroll(密碼的錄入)、verify(密碼的驗證).
調(diào)用流程:locksetting APP ----> IGatekeeperserivce ----> Hardware Gatekeeper HAL ----> Vendor Gatekeeper HAL ----> Gatekeeper TA
- enroll錄入密碼時,locksetting APP將密碼數(shù)據(jù)傳送到TEE的gatekeeper TA,
在TA中先計算signature,計算方法為:HMAC(密碼數(shù)據(jù),hmackey)=signature,
然后再去填充password_handle結(jié)構(gòu)體,最后再將password_handle返回給android,locksetting
APP中再將password_handle保存到文件中. - verify驗證密碼時,locksetting
APP將保存在文件中的password_handle和輸入的密碼數(shù)據(jù)一同傳進TEE的gatekeeper
TA,在TA中先計算signature,計算方法為:HMAC(密碼數(shù)據(jù),hmackey)=signature.
然后再拿這個signature和password_handle中的signature相比較,如果一樣,則返回authToken給android.
在android的IGatekeeperserivce中,將authToken發(fā)送給keystore存儲內(nèi)存中.
同時返回給locksetting APP結(jié)果failed或ok
2、gatekeeper的軟件框圖
(代碼結(jié)構(gòu)圖)
3、enroll和verify的調(diào)用流程
4、重要的結(jié)構(gòu)體
(1)、password_handle
在enroll的時候gatekeeper TA負(fù)責(zé)填充password_handle結(jié)構(gòu)體,返回給android的locksetting保存到文件中.
(system/gatekeeper/include/gatekeeper/password_handle.h) struct __attribute__ ((__packed__)) password_handle_t {uint8_t version;secure_id_t user_id;uint64_t flags;salt_t salt;uint8_t signature[32];bool hardware_backed; };gatekeeper TA是怎樣填充password_handle結(jié)構(gòu)體的?
enrolled_password_handle->version = handle_version enrolled_password_handle->salt = salt enrolled_password_handle->user_id = user_id enrolled_password_handle->flags = flags enrolled_password_handle->hardware_backed = gkbase->IsHardwareBacked() enrolled_password_handle->signature- handle_version:在tee中寫死的2
- salt:每次enroll時,在tee中GetRandom隨機生成
- user_id:第一次enroll時,在tee中GetRandom隨機生成.其實就是SID
- flags : throttle flag,寫死1. 就是是否開啟,失敗密碼次數(shù)計數(shù)功能.
- hardware_backed:為1
- signature: 對密碼進行hmac hash運算得到. 即 HMAC(data,key) = signature
(2)、authToken
在verify通過時候gatekeeper TA填充authToken,返回給android的IGatekeeperService程序,再發(fā)送給keystore保存到內(nèi)存中. (authToken的詳細(xì)介紹可以參考這篇文章)
(hardware/libhardware/include/hardware/hw_auth_token.h) typedef struct __attribute__((__packed__)) {uint8_t version; // Current version is 0uint64_t challenge;uint64_t user_id; // secure user ID, not Android user IDuint64_t authenticator_id; // secure authenticator IDuint32_t authenticator_type; // hw_authenticator_type_t, in network orderuint64_t timestamp; // in network orderuint8_t hmac[32]; } hw_auth_token_t;typedef enum {HW_AUTH_NONE = 0,HW_AUTH_PASSWORD = 1 << 0,HW_AUTH_FINGERPRINT = 1 << 1,// Additional entries should be powers of 2.HW_AUTH_ANY = UINT32_MAX, } hw_authenticator_type_t;- 質(zhì)詢 : challenge
- 用戶SID :user_id
- 身份驗證程序 ID (ASID) : authenticator_id, 身份驗證程序類型 : authenticator_type,00-gatekeeper,01-指紋
5、技術(shù)的細(xì)節(jié)
(1)、failure_record :記錄失敗信息
verify失敗后,會將failure_counter和當(dāng)前的timestamp同時記錄下來,secure_user_id用于索引.
struct __attribute__((packed)) failure_record_t {uint64_t secure_user_id;uint64_t last_checked_timestamp;uint32_t failure_counter; };(2)、throttle : failed_counter和retry_time的規(guī)則
在verify的失敗的時候,需要將失敗的次數(shù)記錄下來,通常的做法是將這個failed_count保存到RPMB中。
在verify成功的時候,再去清除這個數(shù)據(jù).
另外,在verify失敗的時候,還會根據(jù)failed_count值來計算retry_timeout值,retry_timeout最終返回給android側(cè),對應(yīng)的也就是輸錯一次密碼后,還需再等待多數(shù)秒才能進行下一次的輸入. retry_timeout的計算規(guī)則是:
它的計算方式:
(a)、failure_counter為0-4次時,retry_timeout = 0
(b)、failure_counter為5次時,retry_timeout = 30s
?、failure_counter為6-9次時,retry_timeout = 0
(d)、failure_counter為10-29次時,retry_timeout = 30
(e)、failure_counter大于等于30次時,retry_timeout變得更大了,有個指數(shù)增長的過程
由于Gatekeeper TA閉源,我們這里就貼下google的軟實現(xiàn)(寫得不是很好哦)
這種做法意味著,每次verify成功,都會對failed_count操作兩次,如果failed_count是保存在RPMB或某個固定分區(qū)中,那么頻繁的verify顯然容易對這塊分區(qū)或RPMB造成損壞.
在項目設(shè)計中,我們還是建議盡量減少RPMB的讀寫次數(shù)
(3)、timestamp
timestamp是從開機到現(xiàn)在的時間,單位為毫秒. 在TA中是uint64_t timestamp = GetMillisecondsSinceBoot()獲取的.
timestamp的功能有兩個:
a、在gatekeeper TA中的簡單合法校驗
在verify中,比對兩個signature之前,會先檢查RPMB中存儲的的timestamp、根據(jù)RPMB中的failure_counter計算而來的retry_time. 然后進行簡單的邏輯判斷
if (timeout > 0) {// we have a pending timeoutif (timestamp < last_checked + timeout && timestamp > last_checked) {// attempt before timeout expired, return remaining timeresponse->SetRetryTimeout(timeout - (timestamp - last_checked));return true;} else if (timestamp <= last_checked) {// device was rebooted or timer reset, don't count as new failure but// reset timeoutrecord->last_checked_timestamp = timestamp;if (!WriteFailureRecord(uid, record, secure)) {response->error = ERROR_UNKNOWN;return true;}response->SetRetryTimeout(timeout);return true;} }b、 在android中,會對timestamp進行檢查
verify成功后,會將此時的timestamp填充到authToken結(jié)構(gòu)體,返回給android。 android在使用該authToken時,會對timestamp進行檢查.
6、關(guān)鍵函數(shù)的介紹
LockSetting
(1)、writeCredentialHash //將enroll_handle保存到文件
如果是password,保存到passwordFilename, patterFilename寫入空
如果是patter,保存到patterFilename, passwordFilename寫入空
passwordFilename和patterFilename的文件名字分別是:“gatekeeper.password.key”、“gatekeeper.pattern.key”
frameworks/base/services/core/java/com/android/server/locksettings/LockSettingsStorage.java private static final String SYSTEM_DIRECTORY = "/system/"; private static final String LOCK_PATTERN_FILE = "gatekeeper.pattern.key"; private static final String BASE_ZERO_LOCK_PATTERN_FILE = "gatekeeper.gesture.key"; private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key"; private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key"; private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key"; private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key";private static final String SYNTHETIC_PASSWORD_DIRECTORY = "spblob/";Vendor Gatekeeper Hal
(1)、enroll
(函數(shù)原型) int (*enroll)(const struct gatekeeper_device *dev, uint32_t uid,const uint8_t *current_password_handle, uint32_t current_password_handle_length,const uint8_t *current_password, uint32_t current_password_length,const uint8_t *desired_password, uint32_t desired_password_length,uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);- current_password_handle : 輸入?yún)?shù),原來的包含signature的handle結(jié)構(gòu)體,第一次錄入密碼時為空,
修改密碼時使用 - current_password : 輸入?yún)?shù),原來的密碼數(shù)據(jù),第一次錄入密碼時為空, 修改密碼時使用
- desired_password : 輸入?yún)?shù),錄入密碼數(shù)據(jù)(修改后的密碼數(shù)據(jù))
- enrolled_password_handle : 輸出參數(shù),
返回包含signature的handle結(jié)構(gòu)體,交由android保存到文件中.
(2)、verify
(函數(shù)原型) int (*verify)(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge,const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,const uint8_t *provided_password, uint32_t provided_password_length,uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);- enrolled_password_handle : 輸入?yún)?shù),
android中傳來的從文件中讀取的包含signature的handle結(jié)構(gòu)體 - provided_password : 輸入?yún)?shù), 需要驗證的密碼數(shù)據(jù)
- auth_token : 輸出參數(shù) , 在gatekeeper TA
verify成功后會填充authToken結(jié)構(gòu)體返回給android,如果verify失敗,則authToken為NULL
總結(jié)
以上是生活随笔為你收集整理的Android Gatekeeper流程深度解剖的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解android gatekeeper
- 下一篇: android密码解锁/指纹解锁返回的a