日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Gatekeeper流程深度解剖

發布時間:2025/3/21 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Gatekeeper流程深度解剖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

快速鏈接:
.
👉👉👉 個人博客筆記導讀目錄(全部) 👈👈👈


相關推薦:
Android手機使用命令行增加/刪除/修改密碼(password/pin/pattern)
android密碼解鎖/指紋解鎖返回的authToken深度解剖
LockSettingsService的setLockCredentialInternal函數詳解


說明: 在無特別的說明下,本文講述得是android10.0 !

gatekeeper目錄

        • 1、gatekeeper是什么?
        • 2、gatekeeper的軟件框圖
        • 3、enroll和verify的調用流程
        • 4、重要的結構體
          • (1)、password_handle
          • (2)、authToken
        • 5、技術的細節
          • (1)、failure_record :記錄失敗信息
          • (2)、throttle : failed_counter和retry_time的規則
          • (3)、timestamp
            • a、在gatekeeper TA中的簡單合法校驗
            • b、 在android中,會對timestamp進行檢查
        • 6、關鍵函數的介紹
          • LockSetting
            • (1)、writeCredentialHash //將enroll_handle保存到文件
          • Vendor Gatekeeper Hal
            • (1)、enroll
            • (2)、verify

1、gatekeeper是什么?

在android中,gatekeeper是密碼鎖或圖案鎖的一種服務. 主要支持的兩個方法是:enroll(密碼的錄入)、verify(密碼的驗證).

調用流程:locksetting APP ----> IGatekeeperserivce ----> Hardware Gatekeeper HAL ----> Vendor Gatekeeper HAL ----> Gatekeeper TA

  • enroll錄入密碼時,locksetting APP將密碼數據傳送到TEE的gatekeeper TA,
    在TA中先計算signature,計算方法為:HMAC(密碼數據,hmackey)=signature,
    然后再去填充password_handle結構體,最后再將password_handle返回給android,locksetting
    APP中再將password_handle保存到文件中.
  • verify驗證密碼時,locksetting
    APP將保存在文件中的password_handle和輸入的密碼數據一同傳進TEE的gatekeeper
    TA,在TA中先計算signature,計算方法為:HMAC(密碼數據,hmackey)=signature.
    然后再拿這個signature和password_handle中的signature相比較,如果一樣,則返回authToken給android.
    在android的IGatekeeperserivce中,將authToken發送給keystore存儲內存中.
    同時返回給locksetting APP結果failed或ok

2、gatekeeper的軟件框圖


(代碼結構圖)

3、enroll和verify的調用流程

4、重要的結構體

(1)、password_handle

在enroll的時候gatekeeper TA負責填充password_handle結構體,返回給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結構體的?

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. 就是是否開啟,失敗密碼次數計數功能.
  • hardware_backed:為1
  • signature: 對密碼進行hmac hash運算得到. 即 HMAC(data,key) = signature
(2)、authToken

在verify通過時候gatekeeper TA填充authToken,返回給android的IGatekeeperService程序,再發送給keystore保存到內存中. (authToken的詳細介紹可以參考這篇文章)

(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;
  • 質詢 : challenge
  • 用戶SID :user_id
  • 身份驗證程序 ID (ASID) : authenticator_id, 身份驗證程序類型 : authenticator_type,00-gatekeeper,01-指紋

5、技術的細節

(1)、failure_record :記錄失敗信息

verify失敗后,會將failure_counter和當前的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的規則

在verify的失敗的時候,需要將失敗的次數記錄下來,通常的做法是將這個failed_count保存到RPMB中。
在verify成功的時候,再去清除這個數據.
另外,在verify失敗的時候,還會根據failed_count值來計算retry_timeout值,retry_timeout最終返回給android側,對應的也就是輸錯一次密碼后,還需再等待多數秒才能進行下一次的輸入. retry_timeout的計算規則是:
它的計算方式:
(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變得更大了,有個指數增長的過程

(根據failed_counter計算timeout的源碼) uint32_t GateKeeper::ComputeRetryTimeout(const failure_record_t *record) {static const int failure_timeout_ms = 30000;if (record->failure_counter == 0) return 0;if (record->failure_counter > 0 && record->failure_counter <= 10) {if (record->failure_counter % 5 == 0) {return failure_timeout_ms;} else {return 0;}} else if (record->failure_counter < 30) {return failure_timeout_ms;} else if (record->failure_counter < 140) {return failure_timeout_ms << ((record->failure_counter - 30) / 10);}return DAY_IN_MS; }

由于Gatekeeper TA閉源,我們這里就貼下google的軟實現(寫得不是很好哦)
這種做法意味著,每次verify成功,都會對failed_count操作兩次,如果failed_count是保存在RPMB或某個固定分區中,那么頻繁的verify顯然容易對這塊分區或RPMB造成損壞.
在項目設計中,我們還是建議盡量減少RPMB的讀寫次數

(3)、timestamp

timestamp是從開機到現在的時間,單位為毫秒. 在TA中是uint64_t timestamp = GetMillisecondsSinceBoot()獲取的.

timestamp的功能有兩個:

a、在gatekeeper TA中的簡單合法校驗

在verify中,比對兩個signature之前,會先檢查RPMB中存儲的的timestamp、根據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結構體,返回給android。 android在使用該authToken時,會對timestamp進行檢查.

6、關鍵函數的介紹

LockSetting
(1)、writeCredentialHash //將enroll_handle保存到文件

如果是password,保存到passwordFilename, patterFilename寫入空
如果是patter,保存到patterFilename, passwordFilename寫入空

frameworks/base/services/core/java/com/android/server/locksettings/LockSettingsStorage.java public void writeCredentialHash(CredentialHash hash, int userId) {byte[] patternHash = null;byte[] passwordHash = null;if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {passwordHash = hash.hash;} else if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {patternHash = hash.hash;}writeFile(getLockPasswordFilename(userId), passwordHash);writeFile(getLockPatternFilename(userId), patternHash); }

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
(函數原型) 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 : 輸入參數,原來的包含signature的handle結構體,第一次錄入密碼時為空,
    修改密碼時使用
  • current_password : 輸入參數,原來的密碼數據,第一次錄入密碼時為空, 修改密碼時使用
  • desired_password : 輸入參數,錄入密碼數據(修改后的密碼數據)
  • enrolled_password_handle : 輸出參數,
    返回包含signature的handle結構體,交由android保存到文件中.
(2)、verify
(函數原型) 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 : 輸入參數,
    android中傳來的從文件中讀取的包含signature的handle結構體
  • provided_password : 輸入參數, 需要驗證的密碼數據
  • auth_token : 輸出參數 , 在gatekeeper TA
    verify成功后會填充authToken結構體返回給android,如果verify失敗,則authToken為NULL

總結

以上是生活随笔為你收集整理的Android Gatekeeper流程深度解剖的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。