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