日韩性视频-久久久蜜桃-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流程深度解剖的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲精品黄色 | 国产三级在线看 | 松本一香在线播放 | 久久久不卡国产精品一区二区 | 视频在线观看一区 | 国产精品v日韩精品v在线观看 | 国产h视频 | 捆绑少妇玩各种sm调教 | 国产精品久久久久毛片大屁完整版 | 日韩在线视频播放 | 99re在线国产| 久久超碰av| 涩涩涩涩av | 美女av网| 亚洲人成色777777精品音频 | 在线免费观看一级片 | 成人免费自拍视频 | 丰满熟女人妻一区二区三区 | 日韩在线精品 | 狠狠干伊人| 超碰在线中文 | 波多野结衣高清在线 | 黄色性视频网站 | 亚洲熟妇中文字幕五十中出 | 国产综合社区 | 日韩资源在线 | 国产精品久久久久久久久久 | 男男做的视频 | a级特黄视频 | 久久久青草 | 999av视频 | 中文字幕黑丝 | 亚洲小说在线 | 超碰98在线观看 | 国产精品亚洲AV色欲三区不卡 | 国产激情无码一区二区三区 | 日韩久久成人 | 久久成人视屏 | 欧美黄色大片网站 | 亚洲丝袜视频 | 国产成人自拍视频在线观看 | 亚洲精品黄| 成人一区二区三区在线观看 | 国产精品国产馆在线真实露脸 | 欧美放荡性医生videos | 成人午夜在线 | www.日本在线观看 | 在线免费观看a视频 | 国产91精品久久久 | 99riAv国产精品无码鲁大师 | 亚洲AV无码精品黑人黑人 | 色播五月激情 | 奇米av在线| 日韩经典一区二区 | 美女张开腿让人桶 | 丁香花电影在线观看免费高清 | 痴女扩张宫交脱垂重口小说 | 亚洲视频黄色 | 日本精品入口免费视频 | 日韩精品一区在线视频 | 国产精品亚洲二区 | 久久久国产一区 | 综合网色 | 中文一区二区在线观看 | 国产v亚洲v天堂无码 | 亚洲国产精品人人爽夜夜爽 | www.狠狠操 | 成人av在线一区二区 | 午夜中出 | 偷偷久久 | 少妇激情偷人三级 | 中文字幕第12页 | 成人av一区二区在线观看 | 中文字幕亚洲一区二区三区 | 亚洲福利精品 | 亚洲少妇30p | 欧美a在线观看 | 国产国产乱老熟女视频网站97 | аⅴ天堂中文在线网 | 亚洲操操操 | 国产欧美一区二区三区在线看蜜臀 | 麻豆视频成人 | 精品成人国产 | 深夜福利av | 羞羞色视频| 久久国产精品国产精品 | 午夜免费播放观看在线视频 | 国产一线在线 | 爆操欧美| 亚洲老妇色熟女老太 | 日本黄页网站 | 精品一区二区三区中文字幕 | aa视频网站 | 亚洲精品在线一区二区 | 韩国av三级| 精品视频无码一区二区三区 | 精品国产日本 | 国产高清一| 国产美女91呻吟求 |