מערכת המשנה Gatekeeper מבצעת אימות של דפוס/סיסמה של המכשיר ב-Trusted Execution Environment (TEE). Gatekeeper רושם ומאמת סיסמאות באמצעות מפתח סודי בגיבוי חומרה. בנוסף, Gatekeeper מגביל את מספר הניסיונות הרצופים שנכשלו לאימות, וחייב לסרב לבקשות שירות בהתאם לזמן קצוב ולמספר הניסיונות הרצופים שנכשלו.
כשמשתמשים מאמתים את הסיסמאות שלהם, Gatekeeper מפיק אסימון אימות שחתום באמצעות מפתח HMAC לכל אתחול, שזמין רק לרכיבים מאובטחים. האסימון הזה נשלח אל מאגר המפתחות (Keystore) שמגובה בחומרה. כלומר, טוקן אימות של Gatekeeper מודיע ל-Keystore שאפליקציות יכולות להשתמש במפתחות שקשורים לאימות (לדוגמה, מפתחות שאפליקציות יצרו).
ארכיטקטורה
המוצר Gatekeeper כולל שלושה רכיבים עיקריים:
-
gatekeeperd
(Gatekeeper daemon) – שירות C++ Binder ב-Android שמכיל לוגיקה בלתי תלויה בפלטפורמה שמיישמת את ממשק AIDLIGateKeeperService
, על סמך יישום בסיסי ספציפי לספק שלIGatekeeper
. - שירות Gatekeeper HAL (שכבת הפשטה של חומרה) – הטמעה ספציפית לספק של ממשק
IGatekeeper
AIDL. שירות ה-HAL הזה פועל ב-Android, אבל הפונקציונליות העיקרית של Gatekeeper צריכה לפעול בסביבה מאובטחת, ולכן היא בדרך כלל מתקשרת עם Gatekeeper TA. - Gatekeeper Trusted Application (TA) – הטמעה ספציפית לספק שפועלת ב-TEE ומבצעת את האימות בפועל של הסיסמה או קו ביטול הנעילה.
LockSettingsService
שולח בקשה (דרך Binder) שמגיעה לדמון gatekeeperd
במערכת ההפעלה Android. הדימון (daemon) של gatekeeperd
שולח בקשה לשירות HAL של IGatekeeper
, והבקשה מגיעה בתורה ל-Gatekeeper TA המקביל ב-TEE:

איור 1. תרשים זרימת נתונים ברמה גבוהה לאימות באמצעות GateKeeper.
הדמון gatekeeperd
מעניק לממשקי Android framework API גישה ל-HAL, ומשתתף בדיווח על אימותים של מכשירים ל-Keystore.
הדמון gatekeeperd
פועל בתהליך משלו ונפרד משרת המערכת.
הטמעה של HAL
הדמון gatekeeperd
משתמש ב-IGatekeeper
HAL כדי ליצור אינטראקציה עם Gatekeeper TA הבסיסי לצורך אימות סיסמה. ההטמעה של Gatekeeper TA צריכה לאפשר חתימה (הרשמה) ואימות של בלובים. כל ההטמעות צריכות לעמוד בפורמט הסטנדרטי של אסימון האימות (HardwareAuthToken
) שנוצר בכל אימות מוצלח של סיסמה. לפרטים על התוכן והסמנטיקה של HardwareAuthToken
, אפשר לעיין בהגדרה של HardwareAuthToken.aidl
.
ההטמעות של ספקים ב-IGatekeeper
HAL חייבות להטמיע את הפונקציות enroll
ו-verify
:
- השיטה
enroll
מקבלת blob של סיסמה, חותמת אותו ומחזירה את החתימה כ-handle. ל-blob שמוחזר (מקריאה ל-enroll
) צריך להיות המבנה שמוצג ב-system/gatekeeper/include/gatekeeper/password_handle.h
. - הפונקציה
verify
צריכה להשוות את החתימה שנוצרה על ידי הסיסמה שסופקה ולוודא שהיא זהה לסיסמה הרשומה.
המפתח שמשמש לרישום ולאימות לא יכול להשתנות, וצריך להיות ניתן לשחזור בכל אתחול של המכשיר.
Trusty ויישומים אחרים
מערכת ההפעלה Trusty היא מערכת הפעלה מהימנה עם קוד פתוח של Google לסביבות TEE, והיא מכילה הטמעה מאושרת של Gatekeeper. עם זאת, כל מערכת הפעלה של TEE OS יכולה להטמיע את Gatekeeper, כל עוד ל-TEE יש גישה למפתח קבוע בגיבוי חומרה ולשעון מונוטוני מאובטח שפועל במצב השהיה.
Trusty משתמש במערכת IPC פנימית כדי להעביר סוד משותף ישירות בין KeyMint (לשעבר Keymaster) לבין ההטמעה של Gatekeeper ב-Trusty (ה-Trusty Gatekeeper). הסוד המשותף הזה משמש לחתימה על אסימוני אימות שנשלחים אל Keystore כדי לספק אישורים של אימות סיסמה. Trusty Gatekeeper מבקש את המפתח מ-KeyMint לכל שימוש, ולא שומר או מטמון את הערך. ההטמעות יכולות לשתף את הסוד הזה בכל דרך שלא תפגע באבטחה.
מפתח ה-HMAC שמשמש לרישום ולאימות סיסמאות נגזר ונשמר רק ב-Gatekeeper.
Android מספקת הטמעה גנרית של C++ Gatekeeper שנדרש רק להוסיף לה שגרות ספציפיות למכשיר כדי להשלים אותה. ההטמעה של Trusty מבוססת על זה. כדי להטמיע TEE Gatekeeper עם קוד ספציפי למכשיר עבור TEE, אפשר לעיין בפונקציות ובתגובות ב-system/gatekeeper/include/gatekeeper/gatekeeper.h
. האחריות העיקרית של הטמעה תואמת כוללת:
- עמידה בדרישות של
IGatekeeper
HAL. - הפורמט של אסימוני האימות שמוחזרים חייב להיות בהתאם למפרט
HardwareAuthToken
(שמתואר בקטע אימות). - ה-TEE Gatekeeper צריך להיות מסוגל לשתף מפתח HMAC עם KeyMint, או על ידי בקשת המפתח דרך TEE IPC על פי דרישה, או על ידי שמירה של מטמון תקף של הערך בכל רגע נתון.
מזהים מאובטחים של משתמשים (SID)
מזהה אבטחה של משתמש הוא ייצוג של משתמש ב-TEE (בלי קשר חזק למזהה משתמש ב-Android). ה-SID נוצר באמצעות מחולל מספרים פסאודו-אקראיים (PRNG) קריפטוגרפי בכל פעם שמשתמש רושם סיסמה חדשה בלי לספק סיסמה קודמת. הפעולה הזו נקראת הרשמה מחדש לא מהימנה, והיא מתרחשת בדרך כלל רק כשמשתמש מגדיר סיסמה או קו ביטול נעילה בפעם הראשונה.
רישום מחדש מהימן מתרחש כשמשתמש מספק סיסמה קודמת ותקינה, למשל כשמשנים סיסמה. במקרה כזה, ה-SID של המשתמש מועבר לסיסמה החדשה, והמפתחות שקושרו אליה נשמרים.
מזהה האבטחה של המשתמש נכלל באימות ה-HMAC יחד עם הסיסמה בטיפול בסיסמה כשהסיסמה רשומה.
מזהי האבטחה של המשתמשים כלולים ב-HardwareAuthToken
שמוחזר על ידי הפונקציה verify()
ומשויכים לכל המפתחות של Keystore שקשורים לאימות (לפרטים על הפורמט של HardwareAuthToken
ועל Keystore, אפשר לעיין במאמר בנושא אימות).
שימו לב: מכיוון שקריאה לא מהימנה לפונקציה enroll()
משנה את מזהה האבטחה של המשתמש, הקריאה הופכת את המפתחות שמשויכים לסיסמה הזו ללא שימושיים. תוקפים יכולים לשנות את הסיסמה למכשיר אם הם שולטים במערכת Android OS, אבל הם משמידים בתהליך מפתחות רגישים שמוגנים על ידי רוט.
בקשת ויסות נתונים
ל-Gatekeeper צריכה להיות אפשרות לווסת בצורה מאובטחת ניסיונות של מתקפות כוח ברוט על פרטי כניסה של משתמש. כפי שמוצג ב-GatekeeperVerifyResponse.aidl
, HAL מאפשר להחזיר פסק זמן באלפיות השנייה. ההגדרה הזו מודיעה ללקוח לא להתקשר שוב אל Gatekeeper עד שתקופת הזמן הקצובה תסתיים.
אם יש פסק זמן בהמתנה, Gatekeeper לא אמור לטפל בבקשות.
לפני אימות הסיסמה של המשתמש, Gatekeeper צריך לכתוב מונה של כשלים. אם אימות הסיסמה מצליח, מונה הכשלים אמור להתאפס. ההגדרה הזו מונעת מתקפות שמונעות הגבלת קצב העברת נתונים על ידי השבתת ה-MMC המוטמע (eMMC) אחרי ביצוע קריאה של verify
. הפונקציה enroll
מאמתת גם את סיסמת המשתמש (אם היא מסופקת) וצריך להגביל את השימוש בה באותו אופן.
אם המכשיר תומך בכך, מומלץ מאוד לכתוב את מונה הכשלים באחסון מאובטח. אם המכשיר לא תומך בהצפנה מבוססת-קובץ, או אם האחסון המאובטח איטי מדי, יכול להיות שההטמעות ישתמשו ישירות ב-Replay Protected Memory Block (בלוק זיכרון מוגן מפני הפעלה חוזרת, RPMB).